我的目标是在我正在开发的C++游戏中使用全局常量(表示一些图形信息等)。我目前的实现是将它们全部扔在 .h 中并将它们包含在任何地方。这有效,除了每次更改设置时,都必须重新编译整个代码库。
因此,我的下一个想法是将它们扔到某个配置 txt 文件中并解析它们,这样当设置更改时实际上不会更改任何代码。解析器非常简单,我可以将值放入常量中,但由于解析器是代码块,因此常量不再是全局的。
有没有解决这个问题的好方法?也许某种方法使它们全局化,尽管它们处于一个块中,或者以某种方式避免在更改设置时重新编译所有内容?
我使用的解决方法是将变量放在一个单独的全局命名空间中,该命名空间位于名为 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
一样访问它们。
但是,没有"适当"的方法可以解决这个问题,在我看来,所有工作方式都是正确的。
执行此操作的另一种方法是创建一个单例类。
#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;
创建返回可在 .cxx 文件中指定的常量的函数怎么样? 例如:
// foo.h
const int BAR();
// foo.cxx
const int BAR() {
return 10;
};
只把声明放在头文件中,把定义放在 cpp 文件中。 然后你更改 cpp 文件中的定义不会导致所有代码重新编译