在C / C ++中多次包含头文件

在C或C ++中多次包含头文件是否有用?

如果这个机制从来没有被使用,为什么编译器会担心包含一个文件两次; 如果真的没用,如果新的编译器确保每个头只包含一次,会不会更方便?

编辑:

我知道有一些标准的做法,比如包括警卫和杂注 ,但是为什么还要指定呢? 编译器的默认行为不应该只包含一次文件吗?

是的,在用预处理器生成代码或者像Boost.PP这样的技巧时很有用。

有关示例,请参阅Xmacros。 其基本思想是文件包含macros的主体,并且#define参数然后#include它。 这是一个人为的例子:

macro.xpp

 std::cout << MESSAGE; #undef MESSAGE 

file.cpp:

 int main() { # define MESSAGE "hello world" # include "macro.xpp" } 

这也允许你在参数上使用#if和朋友,这是普通的macros所不能做的。

是的,不止一次地包含头文件可能是有用的(虽然这很不寻常)。 典型的例子是<assert.h> ,它根据是否定义NDEBUG来定义不同的asssert 。 因此,把它包含起来是有意义的,然后有一个NDEBUG的定义(通常是有条件的),然后再把它包括进去,至less可能有不同的assert定义:

每次包含<assert.h>时,都会根据NDEBUG的当前状态重新定义assertmacros1

然而,大多数头文件都会带来一些瑕疵,即不pipe它们被包含多less次,都会产生相同的效果。


1 C99,§7.2/ 1。

一个典型的例子(未经testing) – 点是因为它列举了枚举的列表,所以它们一致地出现在enum和stream式代码中:

 // states.h X(Uninitialised) X(Initialised) X(Running) X(Complete) X(Shutdown) // app.c++ #if defined(X) # error X is already defined #endif enum States { #define X(TAG) TAG, #include "states.h" #undef X Extra_So_Trailing_Comma_Ignored }; std::ostream& operator<<(std::ostream& os, const States& state) { #define X(TAG) if (state == TAG) return os << #TAG; #include "states.h" #undef X return os << "<Invalid-State>"; } 

是的,只包含一次会更方便,这就是为什么你使用#pragma一次。 在C ++ 🙂

编辑:

注意:#pragma曾经是不可移植的。 您可以使用

 #ifndef FILENAME_H #define FILENAME_H 

在你的头文件的顶部,而不是如果你想要它是可移植的。

当你需要一些“无聊”的代码生成,你不​​想一次又一次地手工维护时,可以使用多个包含。

经典的例子是一个C / C ++枚举和相应的string,或多或less看起来像这样:

 // MYENUM_VALUES.H MYENUMVALUE(a) MYENUMVALUE(b) MYENUMVALUE(c) MYENUMVALUE(d) // MYENUM.H #define MYENUMVALUE(x) x, enum MyEnum { #include "MYENUM_VALUES.H" } #undef MYENUMVALUE // MYENUMTOSTRING.C #define MYENUMVALUE(x) case x : return #x; const char * MyEnumToString(MyEnum val) { switch (val) { #include "MYENUM_VALUES.H" default return "unknown"; } } #undef MYENUMVALUE 
 #ifndef _INC_HEADER_ #define _INC_HEADER_ //header code #endif 

HEADER是标题的名称

例如。 main_win.h将是_INC_MAIN_WIN_