2011-08-17 13 views
18

Właśnie napisałem klasę z niektórymi statycznymi członkami danych, ale teraz dostaję błędy o "nieokreślonych referencjach". Dlaczego to nie działa? Co ja robię źle?Co to znaczy mieć niezdefiniowane odniesienie do statycznego członka?

(Uwaga:.. Ma to być wstęp do Stack Overflow's C++ FAQ Jeśli chcesz krytyka idei zapewniając nas w tej formie, następnie the posting on meta that started all this byłoby miejsce do tego, że odpowiedzi na to pytanie są monitorowane w C++ chatroom, gdzie FAQ pomysł rozpoczął się w pierwszej kolejności, więc odpowiedź jest bardzo prawdopodobne, aby przeczytać o tych, którzy wpadli na pomysł.)

+0

http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12 – PlasmaHH

Odpowiedz

26

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ę.

+0

"W szczególnym przypadku, jeśli statyczna zmienna składowa jest całką stałą lub typem wyliczenia, może mieć inicjator w definicji klasy ". Czy chodzi ci o deklarację klasy * tutaj? –

+0

@SamGoldberg: Nie - gdybym powiedział _deklaracja_, to odwołałbym się do deklaracji przekazania (np. 'Przykład klasy;'). Przez _ definicję_ rozumiem kod, który deklaruje członków klasy. (Tak, członkowie ci mogą zostać zdefiniowani poza definicją klasy, ale to nie ma znaczenia). – Mankarse

5

Musisz instancję elementy statyczne określone w nagłówek w pliku .cpp. Na przykład:

// foo.h 

class foo { 
    static int X; 
}; 


// foo.cpp 

#include "foo.h" 

int foo::X = 0;