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

Ant*_*ony 4 c++ include

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

例如:

#ifndef A_H
#define A_H

#include<someLibrary.h>

class A{
  ...
}

#endif
Run Code Online (Sandbox Code Playgroud)

然后另一个类包括Ah头

#include<A.h>   //include class A
class B{
   ...
}
Run Code Online (Sandbox Code Playgroud)

我必须在B类中加入"someLibrary.h"吗?

Som*_*ude 9

预处理 #include指令不正是顾名思义,它实际上包括在该指令的地方文件。

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

// Our class
class A
{
    // Stuff for the class
};
// End of the class
Run Code Online (Sandbox Code Playgroud)

然后是一个源文件a.cpp

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

int main()
{
    // Code
}
Run Code Online (Sandbox Code Playgroud)

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

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

int main()
{
    // Code
}
Run Code Online (Sandbox Code Playgroud)

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

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


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


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

没有链接器库的库称为仅标头库。


Bas*_*tch 5

你不包括类或库,你只包括标题,这是一个文本操作(有点像预处理器完成的复制和粘贴)。

阅读有关C/C++ 预处理器GNU cpp 的更多信息

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

对于一个小项目(例如小于 200KLOC),所有翻译单元只包含一个通用头文件是明智的(我认为有很多小头文件是坏习惯,所以我通常每个类定义不止一个头文件)。顺便说一句,这种(单个头文件)方法对预编译头文件很友好。有些人喜欢#include在单个标题中有几个他们自己的-d 子标题。

请注意,大多数 C++ 标准头文件(如<map><vector>....)都带有大量文本,因此您不希望有很小的编译单元(在我的 Linux 系统上,#include <vector>拖了超过一万行,因此只有几行后面的几十行源代码对编译器来说效率低下)

另请注意,C++ 类定义通常具有许多内联成员函数(并且您实际上希望在同一头文件中提供该内联函数的主体)。所以C++头代码往往相当大......

(有些人喜欢在许多子标题中打破单个头文件,这些子标题总是一起包含)

  • _“对于一个小项目(例如小于 200KLOC),所有翻译单元只包含一个通用头文件是明智的”_ oO (2认同)

Lig*_*ica 5

不,#includes是传递性的.

但是,如果您的第二个文件本身使用someLibrary中的符号,则重新包含标题是一种很好的方式.这样你就不会"希望和祈祷"你永远不会删除中间包括.如果每个源文件#include都是它直接需要的所有内容,那么您的代码库将更加强大.标题守卫防止这是一个浪费的政策.