2009-03-13 13 views
10

Ich arbeite an einem Spiel und habe eine interessante Frage. Ich habe einige spielweite konstante Werte, die ich in einer Datei implementieren möchte. Im Moment habe ich so etwas wie diese:C++ beste Möglichkeit, Dateiübergreifende Konstanten zu definieren

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; 

Und dann Dateien nur # include "constants.hpp" Dies funktioniert großartig, bis Ich musste eine der Konstanten als Template-Parameter verwenden, da extern verknüpfte Konstanten keine gültigen Template-Parameter sind. Also meine Frage ist, was ist der beste Weg, um diese Konstanten zu implementieren? Ich befürchte, dass die Konstanten einfach in eine Header-Datei geschrieben werden müssen, damit sie in jeder Übersetzungseinheit definiert werden. Und ich möchte keine Makros verwenden.

Danke

Antwort

19

Befreien Sie sich von der extern und Sie sind eingestellt.

Dieser Code völlig in Ordnung in einem Header funktioniert, weil alles, was „wirklich konstant“ und hat daher interne Bindung:

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

Dieser Code nicht sicher in einer Header-Datei gesetzt werden kann, weil jede Zeile externe Bindung hat (entweder explizit oder wegen nicht wirklich konstant ist):

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

Ich vermute einen Fehler beim Kopieren/Einfügen in letzten BEGINNING_NAME []. Möchtest du es als BEGINNING_NAME schreiben? –

+0

Sie sind richtig, behoben. Vielen Dank. – Tom

+0

Sie benötigen "statisch", sonst erhalten Sie keine interne Verknüpfung oder idealerweise das Äquivalent eines "#define" mit den Werten inline. –

10

Wie wäre es mit enums?

constants.hpp

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

vielleicht etwas entlang der Linien von einer statischen Klasse?

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

Das hilft nicht. Funktionswerte können nicht als Vorlagenparameter verwendet werden. C++ 0x Schlüsselwort "constexpr" soll das umgehen. Außerdem hat C++ Namespaces, die einer statischen Klasse für "Namespacing" -Konstanten überlegen sind. – Tom

+0

* superior * ... Ich habe grundlegende Korrekturlesen Fähigkeiten :) – Tom

0

Die meisten Compiler einfach keinen Platz für const POD Werte zuordnen. Sie optimieren sie und behandeln sie, als wären sie #define d, nicht wahr?

+0

Schließen, aber immer noch nicht ganz das Gleiche. Beispiel, in dem Makros funktionieren, Konstanten jedoch nicht: #define FOO "foo"; \ const char * str = "bar" FOO; C und C++ ermöglichen die Verkettung von String-Literaltoken, nicht jedoch String-Konstanten. – Tom

+0

Dies gilt nur für Integralkonstanten. Floats, Doubles, Char * s und andere Typen erhalten Speicher zugewiesen, wenn die Optimierung deaktiviert ist. –

+0

@Tom: Das habe ich nicht gemeint. Ich meinte für POD-Konstanten, keine Präprozessor-Majicks. Ich meinte in dem Sinne, dass das Symbol und der Raum für den Wert nicht existieren, wenn Sie nicht versuchen, seine Adresse zu nehmen. – greyfade

-5

Als schnelle Antwort auf die Titelfrage ist ein Singleton-Muster eine mögliche, C++ - Methode, um Dateiübergreifende Konstanten zu definieren und nur eine Instanz des Objekts sicherzustellen.

Soweit das Template Parameter Problem, müssen Sie einen Typ nicht einen Wert übergeben. Ihr Typ ist "int".

+0

Dies erscheint als Overkill für eine Reihe von einfachen Konstanten und wird wahrscheinlich nicht seine Probleme mit Template-Instanziierung lösen. – Eclipse

+0

Warum würde nicht sein Problem mit Template Instanziierung lösen, da es kein extern wäre, wäre es ein lokaler. Overkill ist relativ, was ist der Qualitätsaspekt $ 100M, $ 100K oder $ 100 Spielbudget? – jeffD

+0

jeffD, das Problem ist, dass Ihre Antwort keinen Sinn ergibt. Willst du ein "int" ein Singleton machen? Ein Int besteht aus Wert, nicht aus Identität. Eine andere Sache, die Sie wahrscheinlich dazu gebracht hat, Sie zu verärgern, ist, dass er keinen Typ, sondern einen Wert für seine Vorlage weitergeben möchte. Warum sagst du, er kann nicht? –

6

Verwenden Sie "static const int" in Ihrer .hpp-Datei, und legen Sie nichts in die .cpp-Datei (mit Ausnahme von allem anderen Code, den Sie dort natürlich haben).

0

Was auch immer zu einem einfachen passiert:

#define BEGINNING_HEALTH 10 

Man, das waren die Tage.
Oh, warte, diese sind immer noch die Tage!

+0

Das könnte nicht das tun, was Sie im Kontext der Template-Parameter erwarten ... :) rlbond braucht das. –

+4

Einige von uns mögen unsere Debugger, um 'BEGINNING_HEALTH' anstelle von '10' zu zeigen. –

+0

Wann brauchen Sie Debugger, wenn Sie printf() haben? slacy

3

make Verwendung von Namensräumen:

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

dann u kann als Spieler verwenden.Gesundheit = GameBeginning :: GESUNDHEIT;