如何声明和定义全局变量,以便正确地从所有头文件/源文件访问它们

好吧,我正在学习 C ++,从来没有真正学过如何做不是OO的东西。 我想尝试用C风格编写更多经验。

GobalInformation.h

#pragma once #ifndef GLOBALINFORMATION_H #define GLOBALINFORMATION_H #include "MapInformation.h" namespace gi { MapInformation mapInf; }; #endif 

我希望能够从我的项目中的每个头和cpp访问gi :: mapInf。 现在我在每个标题中都包含了globalinformation.h,所以我收到了多个定义的链接器错误。

我该如何解决这个问题?

在头文件中只做

 namespace gi { extern MapInformation mapInf; }; 

在CPP文件中提供实际定义。

 namespace gi { MapInformation mapInf; }; 

它会像你想象的那样工作。

如果跨动态链接库边界使用MapInformation ,则可能必须链接到包含定义cpp文件的库。 同样在Window上你可能需要使用dllimport / dllexport

请注意,在多个编译单元中使用全局变量很容易导致初始化顺序问题。 您可能希望考虑使用返回引用的函数替换每个全局。 在您的情况下,将其放在一个cpp文件中并在标头中声明它:

 namespace gi { MapInformation& getMapInf() { static MapInformation result; return result; } } 

也许更好的解决方案是创建一个包含所有全局数据的全局对象。 然后将智能指针传递给实际需要访问此共享全局数据的类。 例:

 class GlobalData { public: int ticks_; }; //Other file class ThatNeedsGlobalData { public: ThatNeedsGlobalData(std::shared_ptr globalData); }; 

这样可以省去一些麻烦。

祝好运!

全局变量是C,但名称空间是C ++。 关于使用全局变量以及如何用Singleton模式替换它们有很好的讨论: Globals和Singletons

这是一个简单的示例: CPP / Classes / Singleton

以下是您尝试按照使用方式使用全局变量时需要注意的一些事项。

  1. 确保GobalInformation.h包含的头文件的所有头文件也包含在内部#ifndefs中。 (我看不到mapinformation.h所以我假设你已经完成了)

  2. 就像CPP一样,C编译器也不能确保不同翻译单元(不同的C / CPP文件)中变量初始化的顺序。 因此将头文件声明为

     //GlobalInformation.h namespace gi { extern MapInformation mapInf; }; 
  3. 在您知道将要调用的函数中,首先初始化变量。 这种方式也可以在C中实现延迟初始化。