Правильная реализация глобальной конфигурации
Моя цель - иметь глобальные константы в игре на С++, над которой я работаю (для представления некоторой информации о графике и т.п.). Моя текущая реализация заключается в том, чтобы бросить их всех в .h и включить их повсюду. Это работает, за исключением того, что каждый раз, когда я меняю настройку, вся база кода должна быть перекомпилирована.
Итак, моя следующая идея заключалась в том, чтобы бросить их в какой-то конфигурационный txt файл и проанализировать их, таким образом, ни один код не будет изменен при изменении настроек. Парсер был достаточно прост, и я мог поместить значения в константы, но поскольку парсер был блоком кода, константы больше не были глобальными.
Есть ли хороший способ решить эту проблему? Возможно, каким-то образом сделать их глобальными, несмотря на то, что они находятся в блоке или каким-то образом избежать перекомпиляции всего при изменении настроек?
Ответы
Ответ 1
Другой способ сделать это - создать одноэлементный класс.
#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
Способ, которым я использовал, заключается в том, чтобы поместить переменные в отдельное глобальное пространство имен, которое находится в файле заголовка с именем 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
.
Однако, нет "правильного" способа решения этого, все способы, которые работают, правильны в моих глазах.
Ответ 3
Как насчет создания функций, возвращающих ваши константы, которые вы можете указать в файле .cxx? Например:
// foo.h
const int BAR();
// foo.cxx
const int BAR() {
return 10;
};
Ответ 4
помещает только декларации в файл head и помещает определения в файл cpp. то вы измените определения в файле cpp, не вызовет перекомпилированный код