2

当我包含一个头文件时,可以说,

//myheader.h
#ifndef MY_HEADER_H
#define MY_HEADER_H

//....

#endif

进入,

//mycpp1.cpp
#include "myheader.h"

我被告知的是,当 mycpp1.cpp 包含 myheader.h 时,MY_HEADER_H会被定义,因此任何再次包含它的尝试都会导致错误。

现在,如果我想将它包含在 mycpp2.cpp 中。

//mpcpp2.cpp
#include "myheader.h"

它会被包含,还是在第一次包含时使用相同的声明?

4

5 回答 5

6

每个文件的预处理器定义是分开的。因此,如果您将#includemyheader.h 分成两个单独的 .cpp 文件,它将被包含两次,而不是一次。每个 .cpp 一个。

于 2011-12-03T05:31:31.430 回答
4

预处理器定义对于当前编译单元是本地的。

当然有复杂的情况,但重点是:

尝试将 .cpp(源)文件视为不同的实体。如果你不做真正奇怪的事情,那么如果你删除所有 .cpp 文件,除了你打扰的那个,你仍然可以编译,因为在编译阶段不需要定义,你只关心事物的名称(声明)。

因此,一次编译 N 个源文件本质上是这样的:

[ *.H + SOURCE1.CPP ] --> SOURCE1.O
[ *.H + SOURCE2.CPP ] --> SOURCE2.O
...
[ *.H + SOURCEN.CPP ] --> SOURCEN.O

其中每一行都是一个不同的编译单元,它将 SourceX.CPP 和包含的头文件呈现到一个对象文件中。所以我们得到了 N 个单独的东西。

这样,如果您不更改公共头文件,那么您不必重新编译未修改的源文件。当然,如果你修改了一个源文件,你必须重新编译它。最后,如果你修改了一个公共头文件,那么你必须重新编译每个包含它的源文件。这里我不得不提一下,在编译阶段之前,所有 #inlude "filename.ext"行(预处理器指令)都将替换为 filename.ext 文件的确切内容,无论它是什么。

然后链接是一个不同的问题,在那个阶段,目标是从 N 个目标文件创建一个文件。(我重复一遍,这是简单的情况)

这是链接:

[ SOURCE1.O + SOURCE2.O + ... + SOURCEN.O ]  --> EXECUTABLE.FILE

将受影响的目标文件想象成一袋值和算法(函数定义)。例如,包中的某处必须恰好有一个 main函数(定义),因此链接器在您执行程序时肯定会知道要做什么。

希望你明白了

猜猜会发生什么,如果将全局函数的定义写入头文件,然后将其包含在两个单独的编译单元中,然后尝试链接它们。

答案:链接器错误 - 多个定义,因为您可以单独编译它们。

于 2011-12-03T06:09:24.143 回答
3

如果MY_HEADER_H只是定义在 mycpp1.cpp 中,则头文件将包含在 mycpp2.cpp 中

诀窍的真正用途是:

header1.h包括header2.h
因此,当您在 mycpp.cpp 中同时包含header1.hheader2.h时,如果您不这样做, header2.h将被包含两次。

于 2011-12-03T05:36:59.283 回答
1

正如其他人所说,每个 .cpp 文件包含一次头文件。但我还想提一下这样做的全部目的:

#ifndef MY_HEADER_H
#define MY_HEADER_H
// ..
#end if

是为了防止这引起问题

mycpp1.cpp

#include "myheader.h"
#include "myheader.h"
// ...

我开始时遇到的另一件事是,当您将头文件包含在多个 .cpp 文件中并在其中定义了全局变量时...这就是我要解决的问题...

我的头文件

#ifdef MY_HEADER_H
#define MY_HEADER_H

#ifdef GLOBAL_EXTERN
extern int nGlobalInt;
#else
int nGlobalInt = 282;
#endif

#endif

mycpp1.cpp

#include "myheader.h"
// ...

cout << nGlobalInt;

mycpp2.cpp

#define GLOBAL_EXTERN
#include "myheader.h"
// ...

cout << nGlobalInt;

两个 cpp 文件都将打印282

于 2011-12-03T05:46:51.590 回答
-1

它将仅包含一次。指令 MY_HEADER_H 将在第一次包含时定义,随后对#includemyheader.h 的所有尝试都将无效。

预处理器指令在文件中占主导地位。否则,例如,在 myheader.h 中声明的每个类都将被重新定义。

于 2011-12-03T05:44:56.470 回答