2009-03-13 8 views
10

Sto lavorando a un gioco e ho una domanda interessante. Ho alcuni valori costanti per il gioco che voglio implementare in un file. In questo momento ho qualcosa di simile:C++, il modo migliore per definire le costanti del file incrociato

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; 

E poi i file proprio #include "constants.hpp" Questo è stato funzionare grande, fino a quando Avevo bisogno di usare una delle costanti come parametro template, perché le costanti collegate esternamente non sono parametri di template validi. Quindi la mia domanda è: qual è il modo migliore per implementare queste costanti? Temo che il semplice inserimento delle costanti in un file di intestazione causerà la loro definizione in ciascuna unità di traduzione. E non voglio usare macro.

Grazie

risposta

19

Elimina lo extern e sei pronto.

Questo codice funziona perfettamente bene in un colpo di testa, perché tutto è "veramente costante" e, pertanto, ha il collegamento interno:

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

Questo codice non può essere tranquillamente messo in un file di intestazione perché ogni linea ha collegamento esterno (in modo esplicito o a causa di non essere veramente costante):

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

sospetto di un bug di copia/incolla nell'ultimo BEGINNING_NAME []. vuoi scriverlo come BEGINNING_NAME? –

+0

sei corretto, corretto. Grazie. – Tom

+0

È necessario "statico", altrimenti non si ottiene il collegamento interno o, più idealmente, l'equivalente di un "#define" con i valori inline. –

10

E le enumerazioni?

constants.hpp

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

forse qualcosa lungo le linee di una classe statica?

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

Ciò non aiuta. I valori delle funzioni non possono essere utilizzati come parametri del modello. La parola chiave C++ 0x 'constexpr' dovrebbe funzionare su questo. Inoltre, C++ ha spazi dei nomi, che sono superioer di una classe statica per le costanti di "namespacing". – Tom

+0

* superior * ... Mi mancano le competenze di base per la correzione di bozze :) – Tom

0

maggior parte dei compilatori semplicemente non allocano spazio per i valori POD const. Li ottimizzano e li trattano come se fossero stati #define d, no?

+0

Chiudi, ma ancora non del tutto uguale. Esempio in cui le macro funzionano ma le costanti no: #define FOO "foo"; \ const char * str = "bar" FOO; C e C++ consentono la concatenazione di token letterali stringa, ma non costanti stringa. – Tom

+0

Questo vale solo per le costanti integrali. Floating, double, char * s e altri tipi verranno allocati in memoria se l'ottimizzazione è disabilitata. –

+0

@ Tom: non è quello che intendevo. Intendevo per le costanti POD, non per le majicks del preprocessore. Intendevo nel senso che il simbolo e lo spazio per il valore non esistono a meno che tu non provi a prendere il suo indirizzo. – greyfade

-5

Come risposta rapida alla domanda del titolo, un modello singleton è un modo migliore, C++ per definire le costanti del file incrociato e assicurare solo un'istanza dell'oggetto.

Per quanto riguarda il problema dei parametri del modello, è necessario passare un tipo non un valore. Il tuo tipo è "int".

+0

Questo sembra eccessivo per una serie di semplici costanti e non è in grado di risolvere i suoi problemi con l'istanziazione del modello. – Eclipse

+0

Perché non dovrebbe risolvere il suo problema con l'istanziazione del modello, poiché non sarebbe un extern, sarebbe un locale. Overkill è relativo, qual è la prospettiva di qualità $ 100M, $ 100K o $ 100 di budget di gioco? – jeffD

+0

jeffD, il problema è che la tua risposta non ha senso. vuoi fare un "int" singleton? un int è composto dal valore, non dall'identità. un'altra cosa che probabilmente ha fatto in modo che le persone ti abbiano svalutato è che non vuole passare un tipo, ma un valore al suo modello. Perché dici che non può? –

6

Usa "stat const const" nel tuo file .hpp e non metti nulla nel file .cpp (eccetto qualunque altro codice che hai lì, ovviamente).

0

Che cosa mai è successo a un semplice:

#define BEGINNING_HEALTH 10 

uomo, quelli erano i giorni.
Oh aspetta, quelli sono ancora i giorni!

+0

Questo potrebbe non fare quello che ti aspetti nel contesto dei parametri del modello ... :) rlbond ha bisogno di questo. –

+4

Alcuni di noi amano i nostri debugger per mostrare "BEGINNING_HEALTH" anziché "10". –

+0

Quando sono necessari i debugger quando si dispone di printf()? slacy

3

fare uso di namespace:

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

allora la u può usare come lettore.health = GameBeginning :: SALUTE;