static în C++

Are trei sensuri: variabilă locală care își păstrează valoarea între apeluri, membru comun al clasei sau nume vizibil doar în fișierul curent.

Sintaxă
static int contor = 0;            // variabilă locală care își păstrează valoarea
static int membru;                // membru comun tuturor obiectelor clasei
static void metoda();             // metodă apelată fără obiect
static void ajutor();             // funcție vizibilă doar în fișierul curent

Ce face static

Într-o funcție, o variabilă static este creată o singură dată, la primul apel, și își păstrează valoarea între apeluri. Este utilă pentru contoare sau pentru date calculate o singură dată.

Într-o clasă, un membru static aparține clasei, nu fiecărui obiect: există o singură copie, comună tuturor. O metodă static se apelează cu Clasa::metoda(), fără obiect, și nu are acces la this. Din C++17, un membru static poate fi inițializat direct în clasă cu static inline.

În afara oricărei funcții sau clase, static face ca o funcție sau variabilă globală să fie vizibilă doar în fișierul .cpp curent (la fel ca un namespace anonim).

Exemple

Exemplul 1: Variabilă locală statică

numar este inițializat cu 0 o singură dată; fiecare apel continuă de unde a rămas cel anterior.

#include <print>

int urmatorul_bon() {
    static int numar = 0;
    return ++numar;
}

int main() {
    std::println("Bon {}", urmatorul_bon());
    std::println("Bon {}", urmatorul_bon());
    std::println("Bon {}", urmatorul_bon());
}

Rezultat

Bon 1
Bon 2
Bon 3

Exemplul 2: Membru și metodă statică

total este comun tuturor obiectelor Comanda: fiecare constructor îl crește. Comanda::cate() se apelează fără obiect.

#include <print>
#include <string>
#include <utility>

class Comanda {
public:
    explicit Comanda(std::string produs) : produs_(std::move(produs)) { ++total; }
    static int cate() { return total; }
private:
    std::string produs_;
    static inline int total = 0;  // C++17: inițializare în clasă
};

int main() {
    Comanda a("laptop");
    Comanda b("mouse");
    Comanda c("monitor");
    std::println("Comenzi create: {}", Comanda::cate());
}

Rezultat

Comenzi create: 3

Exemplul 3: Funcție vizibilă doar în fișier

#include <print>

static double cu_comision(double suma) {  // nu poate fi folosită din alt fișier .cpp
    return suma * 1.02;
}

int main() {
    std::println("De plată: {:.2f} lei", cu_comision(500));
}

Rezultat

De plată: 510.00 lei

Greșeli frecvente

  • Declari un membru static nenul în clasă (static int total;) și uiți definiția din fișierul .cpp (int Comanda::total = 0;). Primești eroare la legare; din C++17, scrie direct static inline int total = 0;.
  • Încerci să folosești membrii obișnuiți (this->produs_) într-o metodă static. O metodă statică nu are obiect, deci nu are this.
  • Pui o variabilă static locală într-o funcție apelată din mai multe fire de execuție și o modifici. Inițializarea este sigură, dar modificările ulterioare nu: folosește std::atomic sau un std::mutex.

Comenzi înrudite

  • extern: Declară o variabilă sau funcție definită în altă parte (de obicei în alt fișier) sau cere legare în stilul limbajului C.
  • inline: Permite ca o funcție sau variabilă să fie definită în mai multe fișiere (de obicei într-un antet) fără eroare de definiție dublă.
  • class: Definește un tip nou care grupează date (membri) și funcțiile care lucrează cu ele (metode); baza programării orientate pe obiecte.
  • thread_local: Fiecare fir de execuție (thread) primește propria copie a variabilei, creată când pornește firul și distrusă la final.
  • constinit: Garantează că o variabilă globală sau statică este inițializată la compilare, dar fără să o facă constantă.
  • std::atomic: Variabilă care poate fi citită și modificată sigur de mai multe fire, fără mutex.