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

时间:2011-11-29 20:06:11

标签: c++ c global-variables

好吧,我学习 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,所以我收到了多个定义的链接器错误。

我该如何解决这个问题?

5 个答案:

答案 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)

在尝试按照您使用的方式使用全局变量时,您需要注意以下几点。

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

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

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