当我处理个人C和C ++项目时,我通常将file.h
和file.cpp
放在同一目录中,然后file.cpp
可以file.h
引用#include "file.h"
指令。
但是,通常会找到库和其他类型的项目(例如linux内核和freeRTOS),其中所有.h
文件都放在include/
目录中,而.cpp
文件保留在另一个目录中。在这些项目中,.h
文件也包含在#include "file.h"
中,而不是我希望的#include "include/file.h"
。
我对所有这些问题都有疑问:
.h
中的include/
个文件包含在#include "file.h"
而不是#include "include/file.h"
中?我知道真正的技巧是在一些Makefile中,但这样做真的更好,而不是明确(在代码中)我们想要包含的文件实际上在include/
目录中吗?答案 0 :(得分:30)
执行此操作的主要原因是编译的库需要标头才能被最终用户使用。按照惯例,include
目录的内容是公开使用的标题。源目录可能包含供内部使用的标头,但那些不意味着与已编译的库一起分发。
因此,在使用该库时,您链接到二进制文件并将库的include
目录添加到构建系统的标题路径中。同样,如果将已编译的库安装到集中位置,则可以告诉哪些文件需要复制到中心位置(已编译的二进制文件和include
目录)以及哪些文件不是(源文件)目录等等。
答案 1 :(得分:6)
过去,<header>
样式包含隐式路径类型,即在includes
环境变量路径或构建宏上找到,"header"
样式包括显式形式,as-in,完全相对于源文件包含它的位置。虽然一些构建工具链仍然允许这种区别,但它们通常默认为有效地使其无效的配置。
你的问题很有意思,因为它提出了哪个更好,更隐蔽或更明确?隐式形式肯定更容易,因为:
includes
路径中包含几个目录,无需了解有关文件确切位置的所有详细信息。您可以在不更改代码的情况下更改库及其相关标头的版本。另一方面明确表示:
includes
宏/环境变量中的路径进行重新排序,不会更改在构建期间找到的结果头文件。#include "\X\Y\Z"
的确切位置。在隐式表单中,您可能需要沿着多个路径进行搜索,甚至可能找到同一文件的多个版本,您如何知道在构建中使用哪个版本?最好始终对所有标准标题和其他非项目特定的库使用<header>
形式的include,并将"header"
表单用于其他所有内容。您的项目中是否包含本地包含的包含目录?这在某种程度上取决于这些标题是作为接口提供给您的库还是仅由您的代码使用,也取决于您的首选项。你的项目有多大和多么复杂?如果您混合使用内部和外部接口或许多不同的组件,您可能希望将事物分组到不同的目录中。
请记住,您的成品解包的目录结构不需要看起来像开发和构建该产品的目录结构。如果您只有几个.c / .cpp文件和标题,那么&可以将它们全部放在一个目录中,但最终,您将开始处理非平凡的事情,并且必须考虑构建环境选择的后果,并希望将其记录给其他人理解它。
答案 2 :(得分:1)
1。 .hpp和.cpp没有必要有1比1的关系,根据不同的条件(例如:不同的环境),可能有多个.cpp使用相同的.hpp,例如:一个多平台库,想象有一个类获取应用程序的版本,标题是这样的:
Utilities.h
#include <string.h>
class Utilities{
static std::string getAppVersion();
}
的main.cpp
#include Utilities.h
int main(){
std::cout << Utilities::getAppVersion() << std::ends;
return 0;
}
每个平台可能有一个.cpp,而.cpp可能放在不同的位置,以便相应平台可以轻松选择它们,例如:
.cpp for iOS(路径:DemoProject / ios / Utilities.cpp):
#include "Utilities.h"
std::string Utilities::getAppVersion(){
//some objective C code
}
.cpp for Android(路径:DemoProject / android / Utilities.cpp):
#include "Utilities.h"
std::string Utilities::getAppVersion(){
//some jni code
}
当然2 .cpp通常不会同时使用。
2
#include "file.h"
而不是
#include "include/file.h"
允许您在标题不再放入“include”文件夹时保持源代码不变。