在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
的当前状态重新定义assert
macros1 。
然而,大多数头文件都会带来一些瑕疵,即不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_