Stałe i zmienne pola statyczne

2008-02-27 1:06

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:

  1. // foo.hpp
  2. class Foo   { private:   static int ms_iBar; };
  3.  
  4. // foo.cpp
  5. int Foo::ms_iBar = 0;

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:

  1. // foo.hpp
  2. class Foo   { public:   static const int BAR = 10; };
  3.  
  4. // foo.cpp
  5. const int Foo::BAR;

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 ;-)

Tags: , , ,
Author: Xion, posted under Programming »


7 comments for post “Stałe i zmienne pola statyczne”.
  1. x:
    February 27th, 2008 o 13:32

    “…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

  2. Cranegger:
    February 27th, 2008 o 17:17

    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…

  3. raver:
    February 27th, 2008 o 20:46

    I rodzi się pytanie: po co komu stała w jakiejś klasie? Nie lepiej zrobić z niej stałą globalną?

  4. naleth:
    February 27th, 2008 o 20:52

    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:

    1. // foo.hpp
    2. class Foo   { public:   static const int BAR; };
    3.  
    4. // foo.cpp
    5. const int Foo::BAR=10;

    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.

  5. Xion:
    February 27th, 2008 o 21:39

    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 ;-)

  6. moriturius:
    February 29th, 2008 o 12:33

    @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 ;)

  7. kris:
    February 14th, 2014 o 8:45

    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!

Comments are disabled.
 


© 2018 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.