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

how to declare and define global variables in order to access them from all headers/source files properly

本文关键字:源文件 文件 访问 声明 何声明 定义 全局变量      更新时间:2023-10-16

嗯,我在学习 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文件的库。同样在windows上,您可能必须使用dllimport/dllexport

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

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

全局变量是C语言,但命名空间是c++语言。关于如何使用全局变量以及如何用单例模式替换它们,有很好的讨论:全局变量和单例

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

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

class GlobalData
{
public:
    int ticks_;
};   

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

这会省去你很多麻烦。

祝你好运!

在尝试像以前那样使用全局变量时,需要注意以下几点:

  1. 确保GobalInformation.h包含的所有头文件也包含在#ifndefs中。(我看不到地图信息,所以我认为你已经完成了)

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

    //GlobalInformation.h
    namespace gi {
        extern MapInformation mapInf;
    };
    
  3. 在一个你知道会被调用的函数中初始化变量。这种方式也可以在c中实现延迟初始化。