Risposte:
Ovunque in un'unità di compilazione (di solito un file cpp) avrebbe fatto:
foo.h
class foo {
static const string s; // Can never be initialized here.
static const char* cs; // Same with C strings.
static const int i = 3; // Integral types can be initialized here (*)...
static const int j; // ... OR in cpp.
};
foo.cpp
#include "foo.h"
const string foo::s = "foo string";
const char* foo::cs = "foo C string";
// No definition for i. (*)
const int foo::j = 4;
(*) In base agli standard, è necessario definire i
al di fuori della definizione della classe (come j
è) se viene utilizzato in un codice diverso dalle espressioni costanti integrali. Vedi il commento di David sotto per i dettagli.
i
dovrebbe essere definito solo se fosse usato altrove che in espressioni costanti integrali, giusto? In questo caso non si può dire che c'è un errore perché non c'è abbastanza contesto per esserne certi - o in senso stretto l'esempio sopra è corretto se non c'è altro codice. Ora apprezzo molto il tuo commento (+1), sto ancora imparando le cose da solo! Quindi cercherò di chiarire questo punto nella risposta, per favore fatemi sapere se è meglio ...
int f() { return 42; } class foo { static const int i = f(); /* Error! */ }
C ++ 11 consente di chiamare funzioni 'constexpr':constexpr int f() { return 42; } class foo { static const int i = f(); /* Ok */ }
I membri statici devono essere inizializzati in un'unità di traduzione .cpp nell'ambito del file o nello spazio dei nomi appropriato:
const string foo::s( "my foo");
In un'unità di traduzione all'interno dello stesso spazio dei nomi, in genere nella parte superiore:
// foo.h
struct foo
{
static const std::string s;
};
// foo.cpp
const std::string foo::s = "thingadongdong"; // this is where it lives
// bar.h
namespace baz
{
struct bar
{
static const float f;
};
}
// bar.cpp
namespace baz
{
const float bar::f = 3.1415926535;
}
Solo i valori integrali (ad es. static const int ARRAYSIZE
) Vengono inizializzati nel file di intestazione perché vengono generalmente utilizzati nell'intestazione della classe per definire qualcosa come la dimensione di un array. I valori non integrali vengono inizializzati nel file di implementazione.
i
deve essere definito nel cpp. §9.4.2 / 4 Se un membro di dati statici è di tipo const integrale o di enumerazione const, la sua dichiarazione nella definizione della classe può specificare un inizializzatore di costante che deve essere un'espressione di costante integrale (5.19). In tal caso, il membro può apparire in espressioni costanti integrali. Il membro deve ancora essere definito nell'ambito di uno spazio dei nomi se viene utilizzato nel programma e la definizione di ambito dello spazio dei nomi non deve contenere un inizializzatore.