如何避免重复包含头文件

Ita*_*vka 3 c++ macros declaration definition header-files

我有以下代码:

#ifndef GOOGLESET_PHP_H
#define GOOGLESET_PHP_H 
zend_class_entry *googleset_ce;
#endif /* GOOGLESET_PHP_H */
Run Code Online (Sandbox Code Playgroud)

出于某种原因,如果我将此头文件包含在多个cpp文件中,编译器就会喊出我googleset_ce不止一次声明.上面的条件宏不应该足以避免这种情况吗?

Tho*_*ews 7

您需要使用extern关键字:

#ifndef GOOGLESET_PHP_H
#define GOOGLESET_PHP_H

extern zend_class_entry * googleset_ce;

#endif // GOOGLESET_PHP_H
Run Code Online (Sandbox Code Playgroud)

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

这是全球变量不受欢迎的一个原因.


lur*_*her 5

是的,但你只是每个编译单元声明一次.

包含警卫只能确保每个使用它的.cpp声明一次.

因此,如果A.h包括在内B.h并且impl.cpp包括两者,则A.h仅在第一次包含.

在您的情况下,您将包含保护宏的值定义为静态指针变量.因此即使impl.cpp只有一次,impl2.cpp包括相同的文件也会有它们,所以你的静态变量在链接时会有重复的定义

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

myClass* getInstance() {
 static myClass instance;
 return &instance;
 }
Run Code Online (Sandbox Code Playgroud)

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

此外,更相关的是,静态初始化总是在main之前发生,并且不保证顺序.对于静态函数变量,变量是"按需"初始化的,因此它不受初始化排序问题的影响

初始化全局指针:

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

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