E 'importante distinguere il initializer che dice ciò che il suo valore iniziale è, e la definizione di . Questo codice modificato è valido, con l'inizializzatore nella definizione della classe:
class X
{
public:
int normalValue = 5;
static const int i = 0; // declaration, with initializer
};
const int X::i; // definition
cioè cosa deve essere al di fuori della classe è una definizione, non l'inizializzazione.
Questo perché una variabile deve avere un indirizzo nella memoria (meno che non sia utilizzato solo in casi limitati, ad esempio in fase di compilazione espressioni costanti.)
presente una variabile membro static all'interno dell'oggetto che è un membro di, quindi il suo indirizzo dipende dall'indirizzo dell'oggetto che lo contiene. Ogni volta che crei un nuovo X
, crei anche una nuova variabile X::normalValue
. La durata della vita del membro dati non statici inizia con il costruttore della classe. La sintassi NSDMI non ha nulla a che fare con l'indirizzo della variabile in memoria, ma consente semplicemente di fornire un valore iniziale in un posto, invece di ripeterlo in ogni costruttore con un elenco di inizializzatore costruttore esplicito.
D'altra parte, una variabile membro statica non è contenuta all'interno di un'istanza della classe, esiste indipendentemente da una singola istanza ed esiste dall'inizio del programma, ad un indirizzo fisso. Affinché una variabile membro statica (o qualsiasi altro oggetto globale) ottenga un indirizzo univoco, il linker deve vedere esattamente una definizione della variabile statica, esattamente in un file oggetto, e assegnargli un indirizzo.
Poiché una variabile statica richiede esattamente una definizione in esattamente un file oggetto, non ha senso consentire che tale definizione venga fornita nella classe, poiché le definizioni di classe in genere esistono nei file di intestazione e sono incluse in più file oggetto . Quindi, sebbene sia possibile fornire un inizializzatore nella classe, è comunque necessario definire il membro dei dati statici da qualche parte.
si può anche guardare a esso come dichiara un extern
variabile:
namespace X {
extern int i;
}
Questo dichiara la variabile, ma ci deve essere una definizione da qualche parte nel programma:
int X::i = 0;
Perché. ;) Ecco come viene definita la lingua. ;) – jalf
È consentito 'static const int i = 10'. –
@CharlesBeattie, non è ancora una definizione e talvolta è necessaria una definizione, vedere http://gcc.gnu.org/wiki/VerboseDiagnostics#missing_static_const_definition –