包含头文件的困惑

时间:2011-12-03 05:26:03

标签: c++ include-guards

当我包含头文件时,让我们说,

//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"

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

5 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:4)

  

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

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

尝试将.cpp(源)文件视为不同的实体。 如果你没有做出非常奇怪的事情,那么 如果你删除所有.cpp文件,除了你打扰的文件, 你可以编译,因为在编译阶段没有必要 对于定义,您只关心事物的名称(声明)。

因此,在一次运行中编译N个源文件基本上是这样的:

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

其中每一行都是一个独特的编译单元,其中 将SourceX.CPP和包含的标头呈现为Object文件。 所以我们在这里找到了N个单独的东西。

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

然后在那个阶段,链接是一个不同的问题 目标是从N个目标文件创建一个单独的文件。 (我再说一遍,这是一个简单的例子)

这是链接:

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

想象一下受影响的对象文件作为一包价值和 算法(函数定义)。例如,包里的某个地方必须有一个 main函数(定义),因此链接器肯定会知道什么 执行程序时要执行的操作。

希望你明白了

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

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

答案 2 :(得分:3)

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

真正的诀窍是:

  

header1.h 包含 header2.h   因此,当您在mycpp.cpp中包含 header1.h header2.h 时,    header2.h 如果你没有做到这一点,将会被包括两次。

答案 3 :(得分:1)

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

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

是为了防止这种情况造成问题

mycpp1.cpp

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

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

myheader.h

#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

答案 4 :(得分:-1)

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

预处理程序指令优先于文件。否则,例如,myheader.h中声明的每个类都将被重新定义。