2009-03-13 12 views
10

Pracuję nad grą i mam ciekawe pytanie. Mam pewne stałe wartości dla całej gry, które chcę zaimplementować w jednym pliku. Teraz mam coś takiego:C++ najlepszy sposób definiowania stałych krzyżowych

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; 

A potem tylko pliki #include "constants.hpp" to działa świetnie, dopóki Musiałem użyć jednej ze stałych jako parametru szablonu, ponieważ stałe powiązane zewnętrznie nie są poprawnymi parametrami szablonu. Moje pytanie brzmi: jaki jest najlepszy sposób na wprowadzenie tych stałych? Obawiam się, że umieszczenie stałych w pliku nagłówkowym spowoduje ich zdefiniowanie w każdej jednostce tłumaczeniowej. I nie chcę używać makr.

Dzięki

Odpowiedz

19

Pozbądź się extern i gotowe.

Ten kod działa perfekcyjnie w nagłówku, bo wszystko jest „rzeczywiście stała” i dlatego ma wewnętrzną Szkielet:

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

Tego kodu nie można bezpiecznie umieścić w nagłówku pliku, ponieważ każda linia ma powiązania zewnętrzne (albo jawnie, albo dlatego, że nie jest naprawdę stały):

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

Podejrzewam błąd kopiowania/wklejania w ostatnim BEGINNING_NAME [] jeden. Czy chcesz napisać to jako BEGINNING_NAME? –

+0

jesteś poprawny, naprawiony. Dzięki. – Tom

+0

Potrzebujesz "statycznego", w przeciwnym razie nie uzyskasz wewnętrznego powiązania lub, bardziej idealnie, odpowiednika "#define" z wartościami wstawionymi. –

10

Co powiecie na wyliczenia?

constants.hpp

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

może coś wzdłuż linii klasy statyczne?

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

To nie pomaga. Wartości funkcji nie mogą być używane jako parametry szablonu. C++ 0x słowo kluczowe 'constexpr' powinno to obejść. Poza tym C++ ma przestrzenie nazw, które są superioerami do klasy statycznej dla stałych "namespacing". – Tom

+0

* lepszy * ... Brak podstawowych umiejętności korekty :) – Tom

0

Większość kompilatorów po prostu nie rozdziela miejsca dla wartości stałych POD. Optymalizują je i traktują tak, jakby były #define, czyż nie?

+0

Zamknij, ale wciąż nie do końca takie same. Przykład, w którym makra działają, ale stałe nie: #define FOO "foo"; \ const char * str = "bar" FOO; C i C++ pozwalają na łączenie znaczników literału ciągu, ale nie stałych łańcuchowych. – Tom

+0

Dotyczy to tylko stałych integralnych. Pływakom, dwóm, char * s i innym typom zostanie przydzielony magazyn, jeśli optymalizacja jest wyłączona. –

+0

@Tom: Nie o to mi chodziło. Chodzi mi o stałe POD, a nie preprocesory. Miałem na myśli w tym sensie, że symbol i przestrzeń dla wartości nie istnieją, dopóki nie podejmiesz próby adresowania. – greyfade

-5

Jako szybka odpowiedź na pytanie tytułowe, wzór singletonowy jest najlepszym możliwym sposobem C++ do zdefiniowania stałych krzyżowych i zapewnienia tylko jednej instancji obiektu.

Jeśli chodzi o problem z parametrem szablonu, należy podać typ, a nie wartość. Twój typ to "int".

+0

To wydaje się przesadą dla zestawu prostych stałych i prawdopodobnie nie rozwiąże problemów z instancją szablonu. – Eclipse

+0

Dlaczego nie jest rozwiązany problem z instancją szablonu, ponieważ nie byłby on zewnętrznym, byłby lokalny. Overkill jest względny, co to jest perspektywa 100 milionów dolarów, 100 000 $ lub 100 $ budżetu gry? – jeffD

+0

jeffD, problem polega na tym, że twoja odpowiedź nie ma sensu. czy chcesz zrobić "int" singleton? int składa się z wartości, a nie tożsamości. inną rzeczą, która prawdopodobnie skłoniła ludzi do popadnięcia w niechęć jest to, że nie chce przekazać typu, ale wartość do swojego szablonu. Dlaczego mówisz, że nie może? –

6

Użyj "static const int" w pliku .hpp i nie umieszczaj niczego w pliku .cpp (z wyjątkiem tego, co tam masz oczywiście).

0

Co zdarzyło się prosty:

#define BEGINNING_HEALTH 10 

Man, to były czasy.
Och, czekaj, te nadal są dni!

+0

To może nie zrobić tego, czego się spodziewasz w kontekście parametrów szablonu ... :) rlbond tego potrzebuje. –

+4

Niektórzy z nas lubią nasze debuggery, aby pokazać "BEGINNING_HEALTH" zamiast "10". –

+0

Kiedy potrzebne są debuggery, gdy masz printf()? slacy

3

skorzystać z nazw:

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

następnie u można używać jako odtwarzacza.health = GameBeginning :: HEALTH;

Powiązane problemy