This question already has an answer here:
这个问题已经有了答案:
- Is there any situation where you wouldn't want include guards? 6 answers
- 有没有什么情况下你不希望包括警卫?6答案
Is it ever useful to include a header file more than once in C or C++?
在C或c++中多次包含头文件有用吗?
If the mechanism is never used, why would the compiler ever worry about including a file twice; if it really were useless, wouldn't it be more convenient if newer compilers made sure every header is included only once?
如果从未使用过这种机制,为什么编译器会担心包含两次文件?如果它真的没用,如果更新的编译器确保每个头都只包含一次,不是更方便吗?
Edit:
编辑:
I understand that there are standard ways of doing things like include guards and pragma once, but why should you have to specify even that? Shouldn't it be the default behavior of the compiler to include files only once?
我知道有一些标准的方法来做类似的事情,比如警卫和pragma,但是为什么你要具体说明呢?编译器不应该只包含一次文件吗?
6 个解决方案
#1
30
Yes, it's useful when generating code with the preprocessor, or doing tricks like Boost.PP does.
是的,它在使用预处理器生成代码或执行Boost之类的技巧时非常有用。PP。
For an example, see X Macros. The basic idea is that the file contains the body of the macro and you #define
the arguments and then #include
it. Here's a contrived example:
例如,请参见X宏。基本思想是,该文件包含宏的主体,而您#定义参数,然后#包含它。这是一个做作的例子:
macro.xpp
macro.xpp
std::cout << MESSAGE;
#undef MESSAGE
file.cpp:
file.cpp:
int main() {
# define MESSAGE "hello world"
# include "macro.xpp"
}
This also allows you to use #if
and friends on the arguments, something that normal macros can't do.
这也允许你在参数上使用#if和朋友,这是正常宏不能做的。
#2
26
Yes, including a header more than once can be useful (though it is fairly unusual). The canonical example is <assert.h>
, which defines asssert
differently depending on whether NDEBUG
is defined or not. As such, it can make sense to include it, then have a (usually conditional) definition of NDEBUG, followed by including it again, with (at least potentially) different definitions of assert
:
是的,包括一个头不止一次可以是有用的(尽管这是相当不同寻常的)。典型的例子是
The
assert
macro is redefined according to the current state ofNDEBUG
each time that<assert.h>
is included1.assert宏根据每次
是included1。 的ndebug状态重新定义。h>
Most headers, however, go to some pains to be idempotent (i.e., to have the same effects no matter how often they're included).
然而,大多数的标题都要经过一些努力才能变得具有幂等性。,无论它们被包含多少次,都有相同的效果。
1C99, §7.2/1.
1 c99,§7.2/1。
#3
14
A typical example (untested) - point being that it factors a list of enumerations so they appear consistently in an enum
and in streaming code:
一个典型的例子(未经测试)——指出它考虑了枚举列表,因此它们始终出现在枚举和流代码中:
// 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>";
}
#4
4
Yes it would be more convenient only to include it once and that is why you use #pragma once . in C++ :)
是的,只包含一次会更方便,这就是为什么要使用#pragma一次。在c++中:)
Edit:
编辑:
Note: #pragma once is non-portable. You can use
注意:#pragma once是不可移植的。您可以使用
#ifndef FILENAME_H
#define FILENAME_H
in top of your header files instead if you want it to be portable.
在你的头文件上面,如果你想要它是可移植的。
#5
1
Multiple inclusion can be used whenever you need some "boring" code generation that you don't want to maintain by hand, again and again.
当您需要一些不希望手工维护的“无聊”代码生成时,可以反复使用多重包含。
The classic example would be a C/C++ enum and the corresponding strings, which more or less looks like this:
典型的例子是一个C/ c++ enum和相应的字符串,它或多或少是这样的:
// 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
#6
-6
#ifndef _INC_HEADER_
#define _INC_HEADER_
//header code
#endif
Where HEADER
is the header's name
标题的名字在哪里
eg. main_win.h
will be _INC_MAIN_WIN_
如。main_win。h将_INC_MAIN_WIN_
#1
30
Yes, it's useful when generating code with the preprocessor, or doing tricks like Boost.PP does.
是的,它在使用预处理器生成代码或执行Boost之类的技巧时非常有用。PP。
For an example, see X Macros. The basic idea is that the file contains the body of the macro and you #define
the arguments and then #include
it. Here's a contrived example:
例如,请参见X宏。基本思想是,该文件包含宏的主体,而您#定义参数,然后#包含它。这是一个做作的例子:
macro.xpp
macro.xpp
std::cout << MESSAGE;
#undef MESSAGE
file.cpp:
file.cpp:
int main() {
# define MESSAGE "hello world"
# include "macro.xpp"
}
This also allows you to use #if
and friends on the arguments, something that normal macros can't do.
这也允许你在参数上使用#if和朋友,这是正常宏不能做的。
#2
26
Yes, including a header more than once can be useful (though it is fairly unusual). The canonical example is <assert.h>
, which defines asssert
differently depending on whether NDEBUG
is defined or not. As such, it can make sense to include it, then have a (usually conditional) definition of NDEBUG, followed by including it again, with (at least potentially) different definitions of assert
:
是的,包括一个头不止一次可以是有用的(尽管这是相当不同寻常的)。典型的例子是
The
assert
macro is redefined according to the current state ofNDEBUG
each time that<assert.h>
is included1.assert宏根据每次
是included1。 的ndebug状态重新定义。h>
Most headers, however, go to some pains to be idempotent (i.e., to have the same effects no matter how often they're included).
然而,大多数的标题都要经过一些努力才能变得具有幂等性。,无论它们被包含多少次,都有相同的效果。
1C99, §7.2/1.
1 c99,§7.2/1。
#3
14
A typical example (untested) - point being that it factors a list of enumerations so they appear consistently in an enum
and in streaming code:
一个典型的例子(未经测试)——指出它考虑了枚举列表,因此它们始终出现在枚举和流代码中:
// 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>";
}
#4
4
Yes it would be more convenient only to include it once and that is why you use #pragma once . in C++ :)
是的,只包含一次会更方便,这就是为什么要使用#pragma一次。在c++中:)
Edit:
编辑:
Note: #pragma once is non-portable. You can use
注意:#pragma once是不可移植的。您可以使用
#ifndef FILENAME_H
#define FILENAME_H
in top of your header files instead if you want it to be portable.
在你的头文件上面,如果你想要它是可移植的。
#5
1
Multiple inclusion can be used whenever you need some "boring" code generation that you don't want to maintain by hand, again and again.
当您需要一些不希望手工维护的“无聊”代码生成时,可以反复使用多重包含。
The classic example would be a C/C++ enum and the corresponding strings, which more or less looks like this:
典型的例子是一个C/ c++ enum和相应的字符串,它或多或少是这样的:
// 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
#6
-6
#ifndef _INC_HEADER_
#define _INC_HEADER_
//header code
#endif
Where HEADER
is the header's name
标题的名字在哪里
eg. main_win.h
will be _INC_MAIN_WIN_
如。main_win。h将_INC_MAIN_WIN_