Подтвердить что ты не робот

Правильная реализация глобальной конфигурации

Моя цель - иметь глобальные константы в игре на С++, над которой я работаю (для представления некоторой информации о графике и т.п.). Моя текущая реализация заключается в том, чтобы бросить их всех в .h и включить их повсюду. Это работает, за исключением того, что каждый раз, когда я меняю настройку, вся база кода должна быть перекомпилирована.

Итак, моя следующая идея заключалась в том, чтобы бросить их в какой-то конфигурационный txt файл и проанализировать их, таким образом, ни один код не будет изменен при изменении настроек. Парсер был достаточно прост, и я мог поместить значения в константы, но поскольку парсер был блоком кода, константы больше не были глобальными.

Есть ли хороший способ решить эту проблему? Возможно, каким-то образом сделать их глобальными, несмотря на то, что они находятся в блоке или каким-то образом избежать перекомпиляции всего при изменении настроек?

4b9b3361

Ответ 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, не вызовет перекомпилированный код