Aby to zrozumieć, trzeba mieć dobre zrozumienie compiling and linking, a różnice między declarations and definitions.
Rozważmy następujące klasy:
//In header file
class Example {
static bool exampleStaticMember;
};
Tutaj exampleStaticMember
jest zadeklarowany ale nie zdefiniowane. Oznacza to, że jeśli exampleStaticMember
jest używany w sposób, który oznacza, że musi mieć adres, to musi istnieć osobna definicja dla niego. Ogólnie rzecz biorąc, żadna deklaracja statycznego elementu danych w definicji klasy nie jest definicją tego elementu.
Wymagana deklaracja jest zwykle umieszczana w pliku cpp, który zawiera inne definicje członków tej klasy. Musi być w tej samej przestrzeni nazw co definicja klasy. Definicja zazwyczaj wygląda następująco:
//In source file:
//This may optionally have an initialiser (eg "= true")
bool Example::exampleStaticMember;
definicji można umieścić w dowolnym pliku cpp, ale to nie powinno być umieszczone w nagłówku z klasą, bo to mogłoby złamać One Definition Rule.
W szczególnym przypadku, gdy zmienna element statyczny jest const integralną lub wyliczenie typ to może mieć initialiser w definicji klasy:
//In header file
class Example {
static const int initialised = 15;
};
W tym przypadku definicja w pliku cpp jest nadal wymagane, ale nie wolno mieć initialiser: członkowie
//In source file
//Note: no initialiser!
const int Example::initialised;
statyczne, które zostanie zainicjowana w ten sposób mogą być wykorzystane w stałych wyrażeń.
Szablony
Dla statycznego członka danych szablonu, rzeczy są nieco inne. Człon statyczny powinien być zdefiniowany w nagłówku wraz z resztą klasy:
//In header file
template<typename T>
class Example {
static int exampleInt;
static T exampleT;
}
template<typename T> int Example<T>::exampleInt;
template<typename T> T Example<T>::exampleT;
To działa, ponieważ istnieje specyficzny wyjątek od reguły jedną definicję dla statycznych pól szablonów klas.
Inne zastosowania statycznego
Gdy kluczowe static
jest zastosowane do funkcji i obiektów, które nie znajdują się w zakresie klasy może przybrać zupełnie inny sens.
Po zastosowaniu do obiektów w zakresie funkcji deklaruje obiekt zainicjowany w pierwszym wykonaniu funkcji, a następnie przechowuje jego wartość między wywołaniami funkcji.
Po zastosowaniu do obiektów lub funkcji w obszarze przestrzeni nazw (poza dowolną definicją klasy lub funkcji) deklaruje obiekty lub funkcje za pomocą internal linkage. To użycie jest przestarzałe w przypadku obiektów, ponieważ unnamed-namespace stanowi lepszą alternatywę.
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12 – PlasmaHH