如何避免重复包含头文件

发布于 2024-12-11 19:30:15 字数 245 浏览 0 评论 0原文

我有以下代码:

#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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

请远离我 2024-12-18 19:30:15

您需要使用 extern 关键字:

#ifndef GOOGLESET_PHP_H
#define GOOGLESET_PHP_H

extern zend_class_entry * googleset_ce;

#endif // GOOGLESET_PHP_H

否则编译器会认为您在包含此标头的每个文件中声明变量。

这是全局变量不受欢迎的原因之一。

You need to use the extern keyword:

#ifndef GOOGLESET_PHP_H
#define GOOGLESET_PHP_H

extern zend_class_entry * googleset_ce;

#endif // GOOGLESET_PHP_H

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.

何以畏孤独 2024-12-18 19:30:15

是的,但您仅每个编译单元声明一次。

包含防护仅确保每个使用它的 .cpp 声明一次。

因此,如果 Ah 包含在 Bh 中,并且 impl.cpp 包含两者,则 Ah 仅在第一次包含。

在您的情况下,您将 include 保护宏的值定义为静态指针变量。因此,即使 impl.cpp 仅包含一次,包含相同文件的 impl2.cpp 也会包含它们,因此您的静态变量将在链接处具有重复的定义 -如果

你坚持使用静态变量(正如托马斯所说,这通常是糟糕的设计),那么最好将它们包装在一个函数中;

myClass* getInstance() {
 static myClass instance;
 return &instance;
 }

这稍微好一些,因为它确保变量是真正的全局变量,某些体系结构(例如 darwin)的静态变量对于每个动态库而不是每个进程都是唯一的,因此可能会导致令人困惑的行为/可移植性

此外,更相关的是,静态初始化总是发生在 main 之前,并且不保证顺序。 不会受到初始化顺序问题的影响:

对于静态函数变量,变量是“按需”初始化的,因此初始化全局指针

  myClass** getGlobalRef() {
    static myClass* val;
    return &val;
  }

  //and you set it at run-time, avoiding static-initialization happening before main
  * getGlobalRef() = new myClass();

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 in B.h and impl.cpp includes both, then A.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-time

if you insist in having static variables (as Thomas said, it is usually bad design) it is better to wrap them in a function;

myClass* getInstance() {
 static myClass instance;
 return &instance;
 }

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/portability

Also, 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:

  myClass** getGlobalRef() {
    static myClass* val;
    return &val;
  }

  //and you set it at run-time, avoiding static-initialization happening before main
  * getGlobalRef() = new myClass();
夜雨飘雪 2024-12-18 19:30:15

请注意,这是链接器错误,而不是编译器错误。当链接器尝试将所有 *.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 *.cppfiles 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.

默嘫て 2024-12-18 19:30:15

而不是使用“#ifndef GOOGLESET_PHP_H

             #define GOOGLESET_PHP_H 

            #endif /* GOOGLESET_PHP_H */" 

你可以使用

           #pragma once

instead of using "#ifndef GOOGLESET_PHP_H

             #define GOOGLESET_PHP_H 

            #endif /* GOOGLESET_PHP_H */" 

you can use

           #pragma once
与往事干杯 2024-12-18 19:30:15

如果标头包含在多个 .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.

给妤﹃绝世温柔 2024-12-18 19:30:15

lurscher 给出了答案。如果您希望在 .cpp 文件之间共享相同的全局变量,一种方法是在您的 .cpp 文件之一中全局声明它,然后在头文件中将其声明为 extern。

例如:

main.cpp
zend_class_entry *googleset_ce = NULL;

googleset.h
#ifndef GOOGLESET_PHP_H
#define GOOGLESET_PHP_H
extern zend_class_entry *googleset_ce;
#endif /* GOOGLESET_PHP_H */

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:

main.cpp
zend_class_entry *googleset_ce = NULL;

googleset.h
#ifndef GOOGLESET_PHP_H
#define GOOGLESET_PHP_H
extern zend_class_entry *googleset_ce;
#endif /* GOOGLESET_PHP_H */
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文