2012-06-05 8 views
13

Mi objetivo es tener constantes globales en un juego de C++ en el que estoy trabajando (para representar algunos gráficos de información y similares). Mi implementación actual es lanzarlos todos en .h e incluirlos en todos lados. Esto funciona, excepto que cada vez que cambio una configuración, toda la base de código debe recompilarse.Implementación correcta de la configuración global

Por lo tanto, mi siguiente idea fue arrojarlos en algún archivo de configuración de configuración y analizarlos, de esa manera no se cambia el código cuando cambia la configuración. El analizador era bastante simple, y podía poner los valores en las constantes, pero como el analizador era un bloque de código, las constantes ya no eran globales.

¿Hay una buena manera de solucionar esto? ¿Quizás sea una forma de hacerlos globales a pesar de estar en un bloque o de alguna forma evitar volver a compilar todo al cambiar la configuración?

Respuesta

11

Otra forma de hacerlo sería crear una clase singleton.

#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; 
}; 

Aquí, la configuración se guarda en un mapa, es decir, el tiempo que parseFile puede leer el archivo y getValue puede analizar el tipo que no hay necesidad de volver a compilar la clase de configuración si se agrega nuevas llaves.

Uso:

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

Es cierto que originalmente quería hacerlo sin construcciones adicionales como esta, pero esto sigue más convenciones de OO y funciona mejor en general. Me gustaron también las sugerencias de Joachim, pero esta fue la que me resolvió, ¡gracias! – akroy

+1

@akroy Yo no estoy de acuerdo. ¿Qué tipo de convenciones OO quieres decir aquí? Tenemos un singleton. La solución de algún programador parece ser claramente superior a la introducción de un singleton que básicamente se basa en un 'std :: map' con búsqueda lenta y sin seguridad de tipo sin beneficio real sobre las variables – IceFire

+0

¡Oye IceFire! Por contexto, esta pregunta es de hace 5 años cuando estaba aprendiendo a programar. Mirando el hilo de comentarios, parece que también preferí la solución de Algún programador en teoría, pero no pude pasar el compilador. Entonces, si compila para usted, más poder para usted. :) – akroy

1

ponga solo las declaraciones en el archivo principal y ponga las definiciones en un archivo cpp. a continuación, cambie las definiciones en el archivo cpp no ​​causará todo el código recompilado

2

¿Qué ocurre con la creación de funciones que devuelven las constantes que puede especificar en un archivo .cxx? Por ejemplo:

// foo.h 
const int BAR(); 

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

La forma en que solía resolver esto es poner las variables en un espacio de nombres global separada, que está en un archivo de cabecera llamado algo así como config.h, a continuación, incluir ese archivo en todas partes.

// 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 

El en un archivo fuente, que definir la variable y también se configura a un valor predeterminado. Este archivo fuente también tiene el código para cargar las variables desde su archivo de configuración.

// 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 
} 

Ahora en cada archivo fuente que necesitan las variables de configuración, incluyen config.h y accede a ellos como config::some_config_int.

Sin embargo, no hay una forma "adecuada" de resolver esto, todas las formas en que el trabajo es correcto a mis ojos.

+0

Esta solución parece realmente ideal, ya que le permite a cargar en un archivo de configuración, por lo que un usuario podría cambiar la configuración sin ningún tipo de compilación. Pero traté de imitar exactamente la lógica de código que usaste, y obtengo una "referencia indefinida a 'config :: VARIABLE_NAME'" "cada vez que se usa cualquier variable. Incluso cuando no utilicé ninguna función de carga y me limité a definir las variables en .cpp, obtuve el mismo error. (Utilicé la misma sintaxis que con extern en .h y declaración y definición completas en .cpp) – akroy

+0

@Akroy ¿Construye/vincula con el nuevo archivo fuente? –

+0

Sí. Entonces, si config.h tiene espacio de nombres config {extern int x;}, config.cpp tiene namespace config {int x = 5;}, luego en otro archivo que tiene #include "config.h", debería ser capaz de acceder a config :: x? ¿Hay algo que me falta? – akroy

Cuestiones relacionadas