好吧,我学习 C ++并且从未真正学过如何做不是OO的东西。 我想尝试用C风格编写更多经验。
#pragma once
#ifndef GLOBALINFORMATION_H
#define GLOBALINFORMATION_H
#include "MapInformation.h"
namespace gi {
MapInformation mapInf;
};
#endif
我希望能够从我项目中的每个头文件和cpp访问gi :: mapInf。现在我在每个标题中都包含了globalinformation.h,所以我收到了多个定义的链接器错误。
我该如何解决这个问题?
答案 0 :(得分:29)
仅在头文件中执行
namespace gi {
extern MapInformation mapInf;
};
在CPP文件中提供实际定义。
namespace gi {
MapInformation mapInf;
};
它会按你的意愿运作。
如果您在动态链接库边界使用 MapInformation ,则可能必须链接包含定义cpp文件的库。同样在Window上,您可能需要使用 dllimport/dllexport
答案 1 :(得分:12)
请注意,在多个编译单元中使用全局变量很容易导致初始化顺序问题。您可能希望考虑使用返回引用的函数替换每个全局。在您的情况下,将其放在一个cpp文件中并在标题中声明它:
namespace gi {
MapInformation& getMapInf()
{
static MapInformation result;
return result;
}
}
答案 2 :(得分:2)
或许更好的解决方案是创建一个包含所有全局数据的全局对象。然后将智能指针传递给实际需要访问此共享全局数据的类。 例如:
class GlobalData
{
public:
int ticks_;
};
//Other file
class ThatNeedsGlobalData
{
public:
ThatNeedsGlobalData(std::shared_ptr<GlobalData> globalData);
};
这样可以省去一些麻烦。
祝你好运!答案 3 :(得分:2)
全局变量是C,但名称空间是C ++。关于使用全局变量以及如何用Singleton模式替换它们有很好的讨论:Globals and Singletons
这是一个简单的示例:CPP/Classes/Singleton
答案 4 :(得分:1)
在尝试按照您使用的方式使用全局变量时,您需要注意以下几点。
确保GobalInformation.h包含的头文件的所有头文件也包含在#ifndefs中。 (我看不到mapinformation.h所以我假设你已经完成了它)
就像CPP一样,C编译器也不能确保不同翻译单元(不同的C / CPP文件)中变量初始化的顺序。 因此将头文件声明为
//GlobalInformation.h
namespace gi {
extern MapInformation mapInf;
};
在您知道将要调用的函数中,首先初始化变量。这种方式也可以在C中实现延迟初始化。