为什么要在C和C ++项目中创建include /目录?

时间:2018-02-01 03:13:08

标签: c++ c include

当我处理个人C和C ++项目时,我通常将file.hfile.cpp放在同一目录中,然后file.cpp可以file.h引用#include "file.h"指令。

但是,通常会找到库和其他类型的项目(例如linux内核和freeRTOS),其中所有.h文件都放在include/目录中,而.cpp文件保留在另一个目录中。在这些项目中,.h文件也包含在#include "file.h"中,而不是我希望的#include "include/file.h"

我对所有这些问题都有疑问:

  1. 此文件结构组织有哪些优势?
  2. 为什么.h中的include/个文件包含在#include "file.h"而不是#include "include/file.h"中?我知道真正的技巧是在一些Makefile中,但这样做真的更好,而不是明确(在代码中)我们想要包含的文件实际上在include/目录中吗?

3 个答案:

答案 0 :(得分:30)

执行此操作的主要原因是编译的库需要标头才能被最终用户使用。按照惯例,include目录的内容是公开使用的标题。源目录可能包含供内部使用的标头,但那些意味着与已编译的库一起分发。

因此,在使用该库时,您链接到二进制文件并将库的include目录添加到构建系统的标题路径中。同样,如果将已编译的库安装到集中位置,则可以告诉哪些文件需要复制到中心位置(已编译的二进制文件和include目录)以及哪些文件不是(源文件)目录等等。

答案 1 :(得分:6)

过去,<header>样式包含隐式路径类型,即在includes环境变量路径或构建宏上找到,"header"样式包括显式形式,as-in,完全相对于源文件包含它的位置。虽然一些构建工具链仍然允许这种区别,但它们通常默认为有效地使其无效的配置。

你的问题很有意思,因为它提出了哪个更好,更隐蔽或更明确?隐式形式肯定更容易,因为:

  1. 目录层次结构中相关标题的便捷分组。
  2. 您只需在includes路径中包含几个目录,无需了解有关文件确切位置的所有详细信息。您可以在不更改代码的情况下更改库及其相关标头的版本。
  3. DRY
  4. 灵活!您的构建环境不必与我的匹配,但我们通常可以获得几乎完全相同的结果。
  5. 另一方面明确表示:

    1. 可重复构建。对includes宏/环境变量中的路径进行重新排序,不会更改在构建期间找到的结果头文件。
    2. 便携版本。只需打包构建根目录中的所有内容并将其发送给另一个开发者。
    3. 接近信息。您确切知道标题与#include "\X\Y\Z"的确切位置。在隐式表单中,您可能需要沿着多个路径进行搜索,甚至可能找到同一文件的多个版本,您如何知道在构建中使用哪个版本?
    4. 几十年来,构建者一直在争论这两种方法,但两者的混合形式大多胜出,因为纯粹基于显式形式维护构建所需的努力,以及人们可能熟悉的一个和#39; s self,带有纯粹隐含性质的代码。我们通常都明白,我们的各种工具链将某些公共库和标题放在特定的位置,以便它们可以在用户和项目之间共享,因此我们希望在一个地方找到标准的C / C ++标题,但我们不会这样做。 t最初对任何项目的具体结构都知之甚少,缺乏一个本地文档很好的约定,因此我们希望这些项目中的代码对于它们所特有的非标准位是明确的,并且对于标准位是隐含的

      最好始终对所有标准标题和其他非项目特定的库使用<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”文件夹时保持源代码不变。