Storia della domanda
I membri statici delle classi sono apparsi in C++ per consentire di memorizzare valori o funzioni comuni a tutti gli oggetti, non legati a un'istanza specifica della classe. Questo è utile per memorizzare, ad esempio, contatori, fabbriche di oggetti o funzioni ausiliarie.
Problema
Una delle difficoltà è sempre stata l'ambito di visibilità e il momento di inizializzazione di tali membri, specialmente se nel programma ci sono molti file sorgente. Una definizione errata di un membro statico porta a errori di collegamento (linker errors).
Soluzione
In C++, i membri statici vengono dichiarati nella definizione della classe, ma la loro inizializzazione (per le variabili) deve avvenire separatamente nel file cpp (fino a C++17). C++17 consente l'inizializzazione direttamente all'interno della dichiarazione, se è constexpr.
Esempio di codice:
class MyClass { public: static int counter; static void increment() { ++counter; } }; int MyClass::counter = 0; // inizializzazione OBBLIGATORIA al di fuori della classe
Caratteristiche chiave:
Cosa succede se non definisco un membro statico nel file cpp?
Si ottiene un errore di collegamento (linker error), perché la variabile statica sarà dichiarata, ma non definita. Eccezione: se static const int è inizializzato direttamente all'interno della classe per un valore constexpr.
// .h class A { public: static int x; }; // .cpp // int A::x = 0; // se commentato — ci sarà un errore
È possibile chiamare una funzione non statica da una statica?
No. La funzione statica non ha accesso al puntatore this e ai membri non statici direttamente. Per accedere è necessario un oggetto specifico.
class B { int data; static void foo() { // data = 3; // errore } };
Le variabili statiche sono comuni a tutte le istanze?
Sì, nell'ambito di un singolo file eseguibile e processo — lo stesso valore per tutte le istanze.
Nel team hanno dimenticato di definire il membro statico nel file cpp, il progetto occasionalmente si compila con errore, e a volte, usando l'inizializzazione inline (non in tutti i compilatori), si presenta un errore di esecuzione "misterioso".
Pro:
Contro:
Nell'azienda c'è una regola: i membri statici sono sempre definiti nei file cpp per ogni classe. Per la thread-safety vengono utilizzati std::mutex o operazioni atomiche.
Pro:
Contro: