Zmienna statyczna

Zmienna statyczna – w programowaniu jest to zmienna, która w danym bloku programu posiada dokładnie jedną instancję i istnieje przez cały czas działania programu. W języku C++ każda zmienna globalna jest jednocześnie zmienną statyczną.

Zmienna statyczna w bloku funkcji

Zmienna statyczna zadeklarowana w bloku funkcji, zgodnie z definicją pamięta swoją wartość pomiędzy wywołaniami funkcji, co nie jest możliwe przy użyciu zwykłych zmiennych. Przykład w C++:

#include <iostream>

 int podajStatyczna()
 {
   static int x = 0; // deklaracja, definicja i zainicjowanie zmiennej statycznej
   return ++x; // zwiększamy „x” i zwracamy
 }

 int podajZwykla()
 {
   int x = 0; // deklaracja zwykłej zmiennej
   return ++x; // zwiększamy „x” i zwracamy
 }

 int main()
 {
    std::cout << podajStatyczna() << std::endl; //wyświetli 1
    std::cout << podajStatyczna() << std::endl; //wyświetli 2

    std::cout << podajZwykla() << std::endl; //wyświetli 1
    std::cout << podajZwykla() << std::endl; //wyświetli 1
 }

Widzimy zadeklarowaną zmienną statyczną w funkcji podajStatyczna(). Wartość zero jest jej przypisywana tylko raz podczas pierwszego wywołania funkcji. W przeciwieństwie do zwykłej zmiennej, zmienna statyczna nie jest niszczona po wyjściu programu z bloku gdzie została zadeklarowana (w przykładzie wyżej jest to blok funkcji), dzięki temu pamięta swoją wartość pomiędzy wywołaniami funkcji.

Zmienna zadeklarowania w bloku metody w klasie niczym się nie różni od tej zadeklarowanej w bloku funkcji (metoda jest funkcją). Jest wspólna dla wszystkich obiektów klasy, w której zadeklarowana jest dana metoda.

Zmienna statyczna w bloku klasy

Zmienna statyczna zadeklarowana w bloku klasy jest jedyną wspólną instancją dla wszystkich obiektów danej klasy. Jest tworzona już na początku działania programu. Przykład w C++:

 #include <iostream>
 using namespace std;

 class MojaKlasa
 {
   public:
     static int x;
     MojaKlasa() { x++; } // konstruktor - zwiększa „x”
     ~MojaKlasa() { x--; } // destruktor - zmniejsza „x”
 };

 int MojaKlasa::x = 0; // definicja i zainicjowanie zmiennej statycznej „x”

 int main()
 {
   MojaKlasa obiekt1;
   cout << obiekt1.x << endl; //wyświetli 1

   MojaKlasa obiekt2;
   cout << obiekt2.x << endl; //wyświetli 2

   cout << MojaKlasa::x << endl; // nie jest błędem: wyświetli 2

   return 0;
 }

Widzimy zadeklarowaną zmienną statyczną w klasie MojaKlasa. Konstruktor w klasie zwiększa jej wartość, natomiast destruktor zmniejsza. Dzięki temu uzyskaliśmy licznik obiektów klasy MojaKlasa (pominięta została kwestia współbieżności). Każda zmienna statyczna w klasie jest jedynie deklarowana. Z powodu tego, że posiada ona jedną instancję w programie, należy podać również jej definicję, którą realizuje się na zewnątrz deklaracji klasy w zakresie globalnym (należy pamiętać, że nie w każdym języku programowania jest to konieczne). W tym miejscu również następuje zainicjowanie zmiennej. W funkcji main() tworzymy obiekt klasy MojaKlasa. Wyświetlamy aktualną wartość zmiennej statycznej i widzimy wartość 1. Następnie tworzymy drugi obiekt i widzimy, że wartość zmiennej statycznej wynosi już dwa. Zwróćmy uwagę, że za drugim razem odwołujemy się do zmiennej statycznej korzystając z obiektu obiekt2, dzięki temu widzimy, że wszystkie obiekty (w przykładzie są ich 2) współdzielą zmienną statyczną. W kolejnym kroku przedstawiona została technika odwołania się do zmiennej statycznej nie poprzez obiekt, a poprzez nazwę klasy. Jest to spowodowane tym, że zmienne statyczne w klasie istnieją nawet, gdy nie został stworzony żaden obiekt danej klasy. Różnica w C++ polega jedynie na użyciu operatora zakresu ::, zamiast . (w innych językach programowania jak Java czy C# do zmiennych statycznych w klasie odwołujemy się poprzez .).

Zmienne statyczne w bloku klasy nazywane są często polami statycznymi lub zmiennymi klasowymi.

Właściwości i wykorzystanie

  • Zmiennych statycznych używa się jako jedno z rozwiązań uniknięcia używania zmiennych globalnych. Polega ono na zamknięciu zmiennych statycznych we wspólnej klasie. Często deklaruje się taką klasę-kontener, tak aby nie można było stworzyć obiektu tej klasy. Uzyskuje się to poprzez deklarację konstruktorów (co najmniej domyślnego), w sekcji prywatnej klasy (dodatkowo deklaruje się w sekcji prywatnej również konstruktor kopiujący i operator przypisania), np.:
class StaleMatematyczne
 {
   public:
     static const double pi;
     static const double e;

   private:
     StaleMatematyczne() {} // pusty domyślny konstruktor
     StaleMatematyczne( const StaleMatematyczne& wzorzec ) {} // pusty konstruktor kopiujący
     StaleMatematyczne& operator =( const StaleMatematyczne& wzorzec )
     {
       return *this; // pusty operator przypisania
     }
 };

 const double StaleMatematyczne::pi = 3.14159;
 const double StaleMatematyczne::e = 2.71828;

Zobacz też

  • metoda statyczna