正确实施全局配置

时间:2012-06-05 05:41:38

标签: c++ global-variables constants configuration-files

我的目标是在我正在进行的C ++游戏中使用全局常量(表示一些图形信息等)。我目前的实现是将它们全部放在.h中并将它们包含在各处。这是有效的,除了每次更改设置时,必须重新编译整个代码库。

所以,我的下一个想法是将它们放在一些配置txt文件中并解析它们,这样在设置更改时实际上没有代码被更改。解析器很简单,我可以将值放入常量中,但由于解析器是一个代码块,因此常量不再是全局的。

有没有好办法解决这个问题?也许有些方法可以让它们成为全局,尽管它们处于阻塞或某种方式以避免在更改设置时重新编译所有内容?

4 个答案:

答案 0 :(得分:21)

我使用的解决方法是将变量放在一个单独的全局命名空间中,该命名空间位于名为config.h的头文件中,然后在任何地方包含该文件。

// In config.h

#ifndef CONFIG_H
#define CONFIG_H

namespace config
{
    extern int some_config_int;
    extern std::string some_config_string;

    bool load_config_file();
}

#endif

在源文件中,您定义变量并将它们设置为默认值。此源文件还具有从配置文件加载变量的代码。

// In config.cpp

namespace config
{
    int some_config_int = 123;
    std::string some_config_string = "foo";
}

bool config::load_config_file()
{
    // Code to load and set the configuration variables
}

现在,在每个源文件中,您需要配置变量,包括config.h,并像config::some_config_int一样访问它们。

但是,没有“正确”的解决方法,所有工作方式都适合我。

答案 1 :(得分:15)

另一种方法是创建一个单例类。

#include <fstream>
#include <map>
#include <string>

class ConfigStore
{
public:
    static ConfigStore& get()
    {
        static ConfigStore instance;
        return instance;
    }
    void parseFile(std::ifstream& inStream);
    template<typename _T>
    _T getValue(std::string key);
private:
    ConfigStore(){};
    ConfigStore(const ConfigStore&);
    ConfigStore& operator=(const ConfigStore&);
    std::map<std::string,std::string> storedConfig;
};

这里的配置保存在地图中,这意味着只要parseFile可以读取文件并且getValue可以解析该类型,如果添加新密钥则无需重新编译配置类。

用法:

std::ifstream input("somefile.txt");
ConfigStore::get().parseFile(input);
std::cout<<ConfigStore::get().getValue<std::string>(std::string("thing"))<<std::endl;

答案 2 :(得分:2)

如何创建返回可在.cxx文件中指定的常量的函数?例如:

// foo.h
const int BAR();

// foo.cxx
const int BAR() {
    return 10;
};

答案 3 :(得分:1)

只将声明放在头文件中,并将定义放在cpp文件中。那么你改变cpp文件中的定义不会导致所有代码重新编译