在 C 或 C++ 中包含标头的正确方法

Posted

技术标签:

【中文标题】在 C 或 C++ 中包含标头的正确方法【英文标题】:Proper way to include headers in C or C++ 【发布时间】:2015-10-11 23:03:26 【问题描述】:

我刚刚发现我一直在做错事。我没有使用任何 ide,只使用 gcc。我也开始使用 makefile 来编译我的大型项目。

大多数时候文件结构是这样的

├── makefile
└── src
    ├── folder1
    │   ├── header1.cpp
    │   └── header1.h
    ├── folder2
    │   ├── header2.cpp
    │   └── header2.h
    └── main.cpp

header2.cpp 上,当我包含header1.h 时,我会这样做

文件header2.cpp

#include "../folder1/header1.h"

这就是我包含来自另一个文件夹的其他文件的方式。 我认为我做错了。我观看的大部分教程都使用 Ide,但它们并没有像那样包含它。

有些像这样包含它

#include "folder1/header1.h"

或其他人将其放在一个文件夹中,例如 headers/

然后像这样包含它。

#include "header1.h"

谁能指导我。我如何做到这一点。我一直在做这坏事,包括我猜。

我不想包含这样的文件

 #include "../../../../sofarfolder1/header1.h"

谢谢。每次看到我的代码都会让我呕吐。

【问题讨论】:

Makefiles 通常有CFLAGS 选项以使用-I 编译器选项添加到包含路径。在您的情况下,它可能是-Isrc。然后你可以做#include <folderX/headerX.h>。或者如果你把它放在headers 目录中,它会是-Iheader 然后你可以做#include <headerX.h> @AlanAu 更像 CPPFLAGS,因为预处理器是执行所有包括的处理。 【参考方案1】:

如果您不想使用../,可以使用-Idir 标志告诉GCC 在目录dir 中查找头文件。

更多信息:https://gcc.gnu.org/onlinedocs/cpp/Search-Path.html

【讨论】:

【参考方案2】:

https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html

在你的makefile中,你可以用-I../../../sofardirectory调用gcc

这样,它将在该目录中查找您包含的标题。

【讨论】:

【参考方案3】:

使用编译器标志指定其他包含目录的一种不同寻常的替代方法是使用 C 预处理器为包含文件路径创建已定义的常量。

例如,如果您有一个包含相对路径的包含文件,例如 #include "../../stuff/lib1/thing1.h",您可以执行以下操作。

#define THING1_H_PATH  "../../stuff/lib1/thing1.h"
  // ...
#include THING1_H_PATH

gcc C 预处理器文档The C Preprocessor in section 1.3.2, The #include Directive 有这样的说法:

#包含其他内容

此变体称为计算的#include。任何 `#include' 指令 其论点不符合上述两种形式 是一个计算的包含。检查其他任何文本是否有宏 调用,它们被扩展(参见section 1.4 Macros)。完成后, 结果必须符合上述两种变体之一——特别是, 扩展文本最后必须用引号或角包围 大括号。

此功能允许您定义一个宏来控制 稍后在程序中使用的文件名。一份申请 这是为了允许您的站点特定的配置文件 程序指定要使用的系统包含文件的名称。 这有助于将程序移植到各种操作系统 其中必要的系统头文件位于不同的地方。

【讨论】:

【参考方案4】:

我如何处理标头取决于是否要安装它们(如库)。

我会保留在项目源文件夹中的私有标题:

├── Makefile
└── src
    ├── header1.cpp
    └── header1.h
    ├── header2.cpp
    └── header2.h
    └── main.cpp

然后像这样包含它们:

#include "header1.h"

Public headers (to be installed) 我一般放在一个项目子文件夹中是这样的:

├── Makefile
└── src
    ├── project
    │   ├── header1.h
    │   └── header2.h
    └── header1.cpp
    └── header2.cpp
    └── main.cpp

我将它们包括在内:

#include <project/header1.h>

为了定位公共头文件,您需要设置一个编译器标志。对于GCC,即-I

g++ -Isrc ... etc ...

安装标头后,它们会转到/usr/include

 ── usr
    └── include
        ├── project
        │   ├── header1.h
        │   └── header2.h

客户端软件也会以同样的方式包含它们:

#include <project/header1.h>

但他们会提供不同的标志设置来找到它们:

g++ -I/usr/include ... etc ...

【讨论】:

您不应包含来自与&lt;&gt; 相同项目的标头。 "" 就是为此而生的。 @tuple_cat 对于内部项目标题,我使用""。我只使用&lt;&gt; 表示法安装公共标头以供其他人使用。我觉得使用相同的API 很有用,您希望其他人在包含您的标题时使用它。此外,我认为它可以在代码中记录哪些标头是公共API 的一部分,哪些是纯内部的。但是,我当然愿意接受它可能有害的原因?

以上是关于在 C 或 C++ 中包含标头的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

在cmake的所有cpp文件中包含c ++标头[重复]

即使请求标头中包含正确的 x-csrf-token,也不要在 Ajax 帖子上设置 current_user

头文件包含和性能注意事项 c++

如何在Java中包含多个方法?枚举不是正确的方法吗?

在我的 c++ builder 应用程序中包含 xmmintrin.h 的问题

正确设置 Laravel 5 CSRF 令牌的标头