2011-12-03 177 views
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" 

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

回答

6

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

+0

多数民众赞成在我的猜测是..有什么办法,我可以检查,看看它是否包括两次? – user103214

+0

@ user974191您可以在预处理器完成后查看文件,但您为什么要这样做? –

+0

你的意思是目标文件吗?没有什么只是试图了解发生了什么。 – user103214

3

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

什么诀窍是真的就像是:

那么header1.h包括header2.h
所以,当您同时那么header1.hheader2.h在mycpp.cpp, header2.h将被列入如果两次你没有做的伎俩。

-1

它只包含一次。指令MY_HEADER_H将在第一个包含中被定义,并且所有后续尝试到#include myheader.h都不起作用。

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

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

+0

如果没有'#ifdef GLOBAL_EXTERN ...',你的编译器会得到重定义错误。 –

+0

如果你在cpp文件的*一个*里面定义'nGlobalInt'并且摆脱'GLOBAL_EXTERN',它会更直接。 extern充当该变量实例的前向声明。 – greatwolf

+0

@Victor T.,同意......但对于这个问题的背景,我认为这个例子会更好。 –

4

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

当然也有复杂的情况,但这里是点:

尝试看看的.cpp(源)文件作为独立的实体。 如果你没有做出奇怪的事情,那么 如果你删除除了你打扰的所有.cpp文件,你可以stil编译,因为在编译阶段不需要 的定义,你只关心名称(事情声明)。

因此,在一个运行编译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函数(定义),所以链接器肯定会知道在执行程序时要做什么 。

希望你得到它

猜猜会发生什么,如果你写一个全局函数的定义放在一个头文件, 然后你将其包含在两个不同的编译单元,然后尝试将它们连接。

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