2012-06-05 3 views
13

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

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

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

ответ

11

Другой способ сделать это - создать одноэлементный класс.

#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 может прочитать файл и ПолучитьЗначение может разобрать тип там нет необходимости перекомпилировать класс конфигурации при добавлении новых ключей.

Использование:

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

По общему признанию, я изначально хотел сделать это без добавления таких конструкций, как это, но это следует за соглашениями OO и работает лучше вообще! Мне понравились предложения Иоакима, но это то, что решило его для меня, спасибо! – akroy

+1

@akroy Я прошу не согласиться. О каких конвенциях ОО вы вообще имеете в виду? У нас есть синглтон. Некоторое решение программиста-чувака явно превосходит введение синглтона, которое в основном строится вокруг 'std :: map' с медленным поиском и без безопасности типов без реальной выгоды по сравнению с голой переменной – IceFire

+0

Hey IceFire! Для контекста этот вопрос - от 5 лет назад, когда я впервые учился программировать. Глядя на поток комментариев, похоже, я также предпочел решение некоторых программистов-чуваков в теории, но не смог получить его мимо компилятора. Итак, если он компилируется для вас, вам больше силы. :) – akroy

1

положить только декларации в файл head и поместить определения в файл cpp. то вы измените определения в файле cpp, не вызовет все перекомпилированные коды

2

Как насчет создания функций, возвращающих ваши константы, которые вы можете указать в .cxx-файле? Например:

// foo.h 
const int BAR(); 

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

Путь я решить эту проблему, чтобы поместить переменные в отдельном пространстве имен, которое находится в заголовочном файле с именем что-то вроде 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.

Однако, нет «правильного» способа решения этого, все способы, которые работают в моих глазах.

+0

Это решение звучит идеально, потому что это позволяет мне загрузить в конфигурационный файл, так что пользователь может изменить параметры без компиляции. Но я попытался точно подражать используемой логике кода, и я получаю «неопределенную ссылку на« config :: VARIABLE_NAME »« каждый раз, когда используется какая-либо переменная. Даже когда я не использовал какую-либо функцию загрузки и чисто определенную переменные в .cpp, я получил ту же ошибку. (Я использовал тот же синтаксис, что и вы с extern в .h, и полное объявление и определение в .cpp) – akroy

+0

@Akroy Вы создаете/связываете с новым исходным файлом? –

+0

Итак, если config.h имеет пространство имен config {extern int x;}, config.cpp имеет пространство имен config {int x = 5;}, то в другом файле с #include "config.h" я должен иметь доступ к config :: x? Есть ли что-то, что мне не хватает? – akroy

Смежные вопросы