Modyfikator static
ma w C++ kilka różnych funkcji, a jedną z nich jest deklarowanie składników statycznych w klasach. Jak doskonale wiadomo taki składnik jest wspólny dla wszystkich obiektów tejże klasy i można go używać nawet, jeśli takie obiekty w ogóle nie istnieją.
Zwykle nie ma większych problemów ze statycznymi metodami, natomiast w przypadku pól sprawa często potrafi się skomplikować. Zwłaszcza, że statyczne elementy zmienne i stałe deklarujemy nieco inaczej…
Przede wszystkim należy pamiętać, że statyczne zmienne są właściwie pewnym rodzajem zmiennych globalnych, różniącym się prawie wyłącznie pod względem składniowym. A w przypadku zmiennych globalnych (deklarowanych w nagłówkach poprzez extern
) konieczne jest ich przypisanie do jakiegoś modułu kodu, czyli pliku .cpp. Dzięki temu linker może potem powiązać odwołania do tej zmiennej z nią samą niezależnie od miejsca jej użycia.
To samo dotyczy statycznych pól:
Jest jednak drobna różnica między statycznymi stałymi a zmiennymi polami. W tym drugim przypadku możemy zmiennej nadać początkową wartość; robimy to już w pliku .cpp przy jej definicji – tak jak powyżej. Zrobienie tego od razu w deklaracji jest niedopuszczalne.
Natomiast dla stałych wartość podać musimy i zwykle czynimy to dla odmiany właśnie w pliku nagłówkowym, jeszcze wewnątrz bloku class
:
Wówczas z kolei nie możemy wręcz inicjalizować stałej ponownie w pliku .cpp!
Dość dziwne, prawda? Ale w miarę łatwo to wyjaśnić. Otóż stała ma, jak sama nazwa wskazuje stałą wartość. Dzięki temu, że jest podana w nagłówku, kompilator może zoptymalizować każde miejsce jej normalnego użycia. Zamiast odwoływania się do pamięci, wpisze po prostu wartość stałej “na sztywno” w kodzie wynikowym. Będzie więc to podobne do działania #define
.
Tym niemniej jest to pewna niedogodność, jeśli statyczne stałe i statyczne zmienne definiuje się inaczej. Ale przecież to nie jedyna dziwna cecha C++, która sprawia, że tak ten język lubimy ;-)
“…Jest jednak drobna różnica między statycznymi stałymi a zmiennymi polami. W tym drugim przypadku możemy zmiennej nadać początkową wartość; robimy to już w pliku .cpp przy jej definicji – tak jak powyżej. Zrobienie tego od razu w deklaracji jest niedopuszczalne…”
sa sytuacje w ktorych jest to dopuszczalne, oczywiscie według pewnych zasad
Takie wpisy tylko potwierdzają to, że dobrze zrobiłem przechodząc na Javę ;)
Mam wrażenie, że C++ został stworzony dla kompilatorów, a nie programistów…
I rodzi się pytanie: po co komu stała w jakiejś klasie? Nie lepiej zrobić z niej stałą globalną?
Dla stały nie musimy podawać wartości bezpośrednio przy ich deklaracji w klasie – można to zrobić zupełnie oddzielnie, np. w pliku .cpp, i wtedy deklaracja i definicja będą miały taki sam wygląd, jak dla pól niestałych:
W dodatku przypisanie wartości bezpośrednio przy deklaracji takiej stałej jest możliwe tylko wtedy, gdy jest ona typu całkowitoliczbowego. Dlatego nie można powiedzieć, aby był przymus odmiennego sposobu deklarowania zmiennych statycznych stałych/niestałych. Bezpośrednio w deklaracji klasy można to zrobić dla stałych tylko w celu optymalizacji – i to też tylko w specyficznych przypadkach – a nie z przymusu.
x: Jakich? Przecież C++ to nie C# ani Java i nie piszemy tutaj inicjalizacji pól “po znaku =”, tylko na liście inicjalizacyjnej konstruktora.
naleth: Racja, racja. Reasumując:
1) Statyczne stałe pola można inicjalizować w deklaracji tylko, jeśli są typu całkowitego, lecz nawet wtedy nie trzeba tego robić i można inicjalzację umieścić w .cpp. (Drobna nieścisłość w stosunku do tego, co napisałem w notce).
2) Statycznie zmienne pola można inicjalizować tylko w .cpp.
raver: Można też zrobić anonimowy enum ;-)
@Cranegger: jesli lubisz taka – raczej srednia – wydajnosc i ona Ci odpowiada to dobrze zrobiles :P
@raver: żeby nie martwic sie czy nie zabierzesz pozniej nazwy zmiennej, ktora faktycznie musi byc globalna ^^ Inny sposob to wrzucenie jej do jakiegos namespace’a – ale to prawie to samo co wrzucanie do klasy ;)
moge w klasie zadeklarować float, nie koniecznie int
static const float temp;
a w cpp winicjalizowac:
const float CPolarRace::temp = 7.0;
nawet VS 2005 to skompiluje!