#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 库。
如果一个库包含在 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
// 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 库。