2009-03-13 21 views
10

Estoy trabajando en un juego y tengo una pregunta interesante. Tengo algunos valores constantes para todo el juego que quiero implementar en un archivo. Ahora mismo tengo algo como esto:C++ mejor manera de definir constantes de varios archivos

constants.cpp

extern const int BEGINNING_HEALTH = 10; 
extern const int BEGINNING_MANA = 5; 

constants.hpp

extern const int BEGINNING_HEALTH; 
extern const int BEGINNING_MANA; 

Y entonces sólo los archivos # include "constants.hpp" Esto estaba trabajando muy bien, hasta Necesitaba usar una de las constantes como un parámetro de plantilla, porque las constantes vinculadas externamente no son parámetros de plantilla válidos. Entonces mi pregunta es, ¿cuál es la mejor manera de implementar estas constantes? Me temo que simplemente poniendo las constantes en un archivo de encabezado hará que se definan en cada unidad de traducción. Y no quiero usar macros

Gracias

Respuesta

19

Deshágase del extern y listo.

Este código funciona perfectamente bien en un encabezado, porque todo es "verdaderamente constante" y por lo tanto tiene enlace interno:

const int BEGINNING_HEALTH = 10; 
const int BEGINNING_MANA = 5; 
const char BEGINNING_NAME[] = "Fred"; 
const char *const BEGINNING_NAME2 = "Barney"; 

Este código no puede con seguridad puede poner en un archivo de cabecera, ya que cada línea tiene enlazado externo (ya sea explícitamente o porque de no ser realmente constante):

extern const int BEGINNING_HEALTH = 10; 
extern const int BEGINNING_MANA = 5; 
const char *BEGINNING_NAME = "Wilma"; // the characters are const, but the pointer isn't 
+0

sospecho que hay un error de copiar/pegar en el último BEGINNING_NAME [] uno. ¿Querías escribirlo como BEGINNING_NAME? –

+0

estás en lo correcto, arreglado. Gracias. – Tom

+0

Necesita "estática", de lo contrario no obtendrá un enlace interno o, más idealmente, el equivalente de un "#define" con los valores en línea. –

10

¿Qué hay de enums?

constants.hpp

enum { 
    BEGINNING_HEALTH = 10, 
    BEGINNING_MANA = 5 
    } 
-2

tal vez algo en la línea de una clase estática?

class CONSTANTS { 
public: 
static inline int getMana() { return 10;}; 
}; 
+0

Eso no ayuda. Los valores de función no se pueden usar como parámetros de plantilla. Se supone que la palabra clave C++ 0x 'constexpr' funciona alrededor de eso. Además, C++ tiene espacios de nombre, que son superioer a una clase estática para las constantes de "espacio de nombres". – Tom

+0

* superior * ... Me faltan habilidades básicas de corrección :) – Tom

0

mayoría de los compiladores simplemente no asignar espacio para los valores POD const. Los optimizan y los tratan como si hubieran sido #define d, ¿no?

+0

Cerrar, pero todavía no es lo mismo. Ejemplo donde las macros funcionan pero las constantes no: #define FOO "foo"; \ const char * str = "bar" FOO; C y C++ permiten la concatenación de tokens literales de cadena, pero no constantes de cadena. – Tom

+0

Esto solo es válido para las constantes integrales. Flotantes, dobles, charlatas y otros tipos se asignarán de almacenamiento si la optimización está deshabilitada. –

+0

@Tom: Eso no es lo que quise decir. Me refería a las constantes POD, no al preprocessor majicks. Quise decir en el sentido de que el símbolo y el espacio para el valor no existen a menos que intentes tomar su dirección. – greyfade

-5

Como una respuesta rápida a la pregunta del título, un patrón singleton es una posible forma mejor, C++ para definir constantes entre archivos y asegurar solo una instancia del objeto.

En cuanto al problema del parámetro de plantilla, debe pasar un tipo, no un valor. Tu tipo es "int".

+0

Esto parece exagerado para un conjunto de constantes simples, y no es probable que resuelva sus problemas con la creación de instancias de plantillas. – Eclipse

+0

Por qué no resolvería su problema con la creación de instancias de plantillas, ya que no sería un elemento externo, sería un local. Overkill es relativo, ¿cuál es la perspectiva de la calidad de $ 100M, $ 100K o $ 100 del presupuesto del juego? – jeffD

+0

jeffD, el problema es que su respuesta no tiene sentido. ¿Quieres hacer un "int" un singleton? un int está compuesto por valor, no por identidad. Otra cosa que probablemente hizo que la gente te menosprecie es que no quiere pasar un tipo, sino un valor para su plantilla. ¿Por qué dices que no puede? –

6

Utilice "static const int" en su archivo .hpp, y no coloque nada en el archivo .cpp (excepto cualquier otro código que tenga, por supuesto).

0

¿Qué pasó con un simple:

#define BEGINNING_HEALTH 10 

hombre, esos eran los días.
¡Oh, espera, esos todavía son los días!

+0

Eso podría no hacer lo que estás esperando en el contexto de los parámetros de la plantilla ... :) rlbond necesita eso. –

+4

A algunos de nosotros les gusta que nuestros depuradores muestren 'BEGINNING_HEALTH' en lugar de '10'. –

+0

¿Cuándo necesita depuradores cuando tiene printf()? slacy

3

hacer uso de espacios de nombres:

namespace GameBeginning { 
    const int HEALTH = 10; 
    const int MANA = 5; 
}; 

entonces u puede utilizar como reproductor.salud = GameBeginning :: SALUD;

Cuestiones relacionadas