如何避免重复包含头文件
我有以下代码:
#ifndef GOOGLESET_PHP_H
#define GOOGLESET_PHP_H
zend_class_entry *googleset_ce;
#endif /* GOOGLESET_PHP_H */
由于某种原因,如果我在多个 cpp 文件中包含此头文件,编译器会大声喊叫我多次声明 googleset_ce
。上面的条件宏是否足以避免这种情况?
I have the following code:
#ifndef GOOGLESET_PHP_H
#define GOOGLESET_PHP_H
zend_class_entry *googleset_ce;
#endif /* GOOGLESET_PHP_H */
For some reason if I include this header file in more than one cpp file, the compiler shouts that I am declaring googleset_ce
more than once. Shouldn't the conditional macros above be enough to avoid this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您需要使用
extern
关键字:否则编译器会认为您在包含此标头的每个文件中声明变量。
这是全局变量不受欢迎的原因之一。
You need to use the
extern
keyword:Otherwise the compiler thinks you are declaring the variable in every file that includes this header.
This is one reason global variables are frowned upon.
是的,但您仅每个编译单元声明一次。
包含防护仅确保每个使用它的 .cpp 声明一次。
因此,如果
Ah
包含在Bh
中,并且impl.cpp
包含两者,则Ah
仅在第一次包含。在您的情况下,您将 include 保护宏的值定义为静态指针变量。因此,即使
impl.cpp
仅包含一次,包含相同文件的impl2.cpp
也会包含它们,因此您的静态变量将在链接处具有重复的定义 -如果你坚持使用静态变量(正如托马斯所说,这通常是糟糕的设计),那么最好将它们包装在一个函数中;
这稍微好一些,因为它确保变量是真正的全局变量,某些体系结构(例如 darwin)的静态变量对于每个动态库而不是每个进程都是唯一的,因此可能会导致令人困惑的行为/可移植性
此外,更相关的是,静态初始化总是发生在 main 之前,并且不保证顺序。 不会受到初始化顺序问题的影响:
对于静态函数变量,变量是“按需”初始化的,因此初始化全局指针
yes, but you are only declaring it once per compilation unit.
include guards only make sure you declare things once per .cpp that uses it.
So if
A.h
is included inB.h
andimpl.cpp
includes both, thenA.h
is included only the first time.In your case, you are defining the value of the include guard macro as a static pointer variable. So even if
impl.cpp
has it only once,impl2.cpp
which includes the same files will have them as well, so your static variable will have duplicate definitions at link-timeif you insist in having static variables (as Thomas said, it is usually bad design) it is better to wrap them in a function;
this is slightly better because it makes sure the variable is truly global, some architectures (like darwin) have that
static
variables are unique per dynamic library, not per process, so it might led to confusing behavior/portabilityAlso, and more relevant, static initialization always happens before main, and the order is not guaranteed. With static function variables, the variables are initialised "on demand" and so it is not affected by initialization ordering issues
to initialise a global pointer:
请注意,这是链接器错误,而不是编译器错误。当链接器尝试将所有
*.cpp
文件(包括头文件)的目标文件 (*.o
) 放在一起时,您会得到一个多重定义的符号。您可能会使用
extern
关键字使符号唯一来解决该问题。并在一个(且仅有一个).cpp
文件中的其他位置声明它。Beware that it is a linker error, not a compiler error. You get a multiple defined symbol when the linker tries to put together the object files (
*.o
) for all the*.cpp
files including the header file.You would probably work around the problem using the
extern
keyword to make the symbol unique. And declaring it somewhere else in one (and only one).cpp
file.而不是使用“#ifndef GOOGLESET_PHP_H
你可以使用
instead of using "#ifndef GOOGLESET_PHP_H
you can use
如果标头包含在多个 .c/.cpp 文件中,那么它确实可能在多个 .obj 文件中声明。
您必须将其封装在命名空间或类中,这样它就不会被视为包含它的每个 .cpp 文件的全局变量。
If the header is included in several .c/.cpp files then indeed it's potentially declared in multiple .obj files.
You have to encapsulate it in a namespace or a class so it's not considered as a global variable for each .cpp file that includes it.
lurscher 给出了答案。如果您希望在 .cpp 文件之间共享相同的全局变量,一种方法是在您的 .cpp 文件之一中全局声明它,然后在头文件中将其声明为 extern。
例如:
lurscher has the answer. If you're looking to share the same global variable across .cpp files, one way to do it is to declare it globally in one of your .cpp files, then declare it as extern inside the header file.
For example: