为什么在c ++中包含两次头文件是有效的?

use*_*729 5 c++ syntax

#include "DLLDefines.h"
#include "DLLDefines.h"
Run Code Online (Sandbox Code Playgroud)

以上实际上是通过编译,但为什么呢?

jal*_*alf 14

嗯,这是合法的,因为它必须是合法的.因为您经常多次包含相同的标题,甚至没有意识到它.

您可以在.cpp文件中包含两个标头,每个标头包含许多文件,其中一些文件可能包含在内.

例如,所有标准库标题(例如,string或者说vector)都可能包含在大多数标题中.因此,您很快就会在同一个.cpp文件中多次间接包含相同的标头.

简而言之,它必须工作,否则所有C++代码都会崩溃.

至于它是如何工作的,通常是通过包括警卫.请记住,#include只需执行简单的复制/粘贴:它会在#include站点中插入头文件的内容.

因此,假设您有一个header.h包含以下内容的头文件:

class MyClass {};
Run Code Online (Sandbox Code Playgroud)

现在让我们创建一个cpp文件,其中包含两次:

#include "header.h"
#include "header.h"
Run Code Online (Sandbox Code Playgroud)

预处理器将其扩展为:

class MyClass {};
class MyClass {};
Run Code Online (Sandbox Code Playgroud)

这显然会导致错误:同一个类被定义两次.所以这不起作用.相反,让我们修改标题以包含包含警戒:

#ifndef HEADER_H
#define HEADER_H

class MyClass {};

#endif
Run Code Online (Sandbox Code Playgroud)

现在,如果我们将它包括两次,我们得到这个:

#ifndef HEADER_H
#define HEADER_H

class MyClass {};

#endif

#ifndef HEADER_H
#define HEADER_H

class MyClass {};

#endif
Run Code Online (Sandbox Code Playgroud)

这是预处理器处理时发生的情况:

#ifndef HEADER_H // HEADER_H is not defined, so we enter the "if" block
#define HEADER_H // HEADER_H is now defined

class MyClass {};// MyClass is now defined

#endif           // leaving the "if" block

#ifndef HEADER_H // HEADER_H *is* defined, so we do *not* enter the "if" block
//#define HEADER_H
//
//class MyClass {};
//
#endif           // end of the skipped "if" block
Run Code Online (Sandbox Code Playgroud)

因此,最终结果是MyClass只定义了一次,即使标题包含两次.因此生成的代码是有效的.

这是头文件的重要属性.始终定义标题,以便多次包含它们.


CB *_*ley 8

这取决于头文件; 对同一文件的多个包含没有语言限制.

某些文件被设计为包含多次(例如,<assert.h>可以多次包含以打开'和'关闭' assert).

许多文件可以安全地被多次包含,因为它们包括防护,其他文件不包括在翻译单元甚至程序中.


pli*_*nth 6

include与C或C++语言无关.它是预处理器引入文件的指令.预处理器不关心引入什么文件,也不应该关心.这样做可能完全可以接受:

void Foo::SomeFunc(int cond)
{
    switch (cond) {
    case kThisCase:
#include "longFirstCase.h"
        break;
    case kSecondCase:
#include "longSecondCase.h"
        break;
    case kThirdCase:
#include "longFirstCase.h"
#include "longSecondCase.h"
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经多次看到同一个文件作为配置机制.

当然,有很多方法可以将这个例子考虑得更好,但关键是你可能会有很好的理由,因此对使用没有任何限制.


小智 4

可能您的代码周围的 DLLDefines.h 中有一些#define,以防止它被包含两次。

#ifndef DLLDEFINES_H
#define DLLDEFINES_H
// your code
#endif
Run Code Online (Sandbox Code Playgroud)

  • 吹毛求疵:这种技术并不能阻止它被包含两次;它可以安全地多次包含它。 (7认同)