#include 在 C++ 中如何工作?

How does #include work in C++?

如果一个库包含在 class header 中,然后这个 header 包含在另一个 class 中,我是否必须再次包含该库?

例如:

#ifndef A_H
#define A_H

#include<someLibrary.h>

class A{
  ...
}

#endif

然后另一个class包括A.hheader

#include<A.h>   //include class A
class B{
   ...
}

我必须在 class B 中包含 "someLibrary.h" 吗?

您不包括 classes 或库,您只包括 headers,这是一个 textual 操作(有点像由预处理器完成的复制和粘贴)。

阅读有关 C/C++ preprocessor, and the GNU cpp 的更多信息。

您可以要求您的编译器向您显示源文件的预处理形式 foo.cc,例如使用 g++ -Wall -C -E foo.cc(它会溢出 stdout 预处理形式)

对于一个小项目(例如小于 200KLOC),所有翻译单元只包含一个公共 header 文件是明智的(我相信有许多小 header 文件是坏习惯,所以我通常在每个 header 文件中放置多个 class 定义)。顺便说一句,(单个 header 文件)方法对 precompiled headers 很友好。有些人喜欢在单个 header.

中有几个自己的 #include-d subheader

请注意,大多数 C++ 标准 headers(如 <map><vector>...)会带来大量文本,因此您不希望进行微小的编译单位(在我的 Linux 系统上,#include <vector> 拖拽了一万多行,所以只有几十行源代码行对编译器来说效率很低)

另请注意,C++ class 定义通常有很多内联成员函数(实际上您希望在同一 header 文件中提供该内联函数的 body)。所以 C++ header 代码往往相当大...

(有些人喜欢将单个 header 文件分解成许多子 header,它们总是包含在一起)

不,#include是可传递的。

但是,如果您的第二个文件本身使用了来自 someLibrary 的符号,那么 re-include 和 header 的风格是不错的。这样你就不会 "hoping and praying" 你永远不会删除中间包含。如果每个源文件 #include 包含它直接需要的所有内容,您的代码库将更加健壮。 Header 守卫防止这是一个浪费的政策。

preprocessor #include 指令的作用正如其名称所暗示的那样,它实际上 包含 指令所在位置的文件。

简单的例子:假设我们有文件,首先是一个名为 a.h

的 header 文件
// Our class
class A
{
    // Stuff for the class
};
// End of the class

然后一个源文件a.cpp:

// Include header file
#include "a.h"
// Header file included

int main()
{
    // Code
}

预处理器生成一个单个文件,看起来像

// Include header file
// Our class
class A
{
    // Stuff for the class
};
// End of the class
// Header file included

int main()
{
    // Code
}

这种包含是递归的,所以如果一个 header 文件包含另一个 header 文件,那么另一个 header 文件也将被包含。

预处理器生成的源文件称为translation unit,是编译器实际看到的。


以上是对现代预处理器工作方式的简化,虽然可以 运行 单独创建预处理源文件,但更常见的是预处理器是编译器的一部分以简化解析过程。


您还应注意,您使用的术语不正确。一个库可以(通常确实)有一个或多个 header 文件,这些文件在编译源代码时会用到。然后,库通常(但不总是)包含一个特殊的库文件,该文件与编译器创建的 object 文件 链接

没有链接器库的库被称为仅 header 库。