Geschichte der Frage
Statische Klassenmitglieder wurden in C++ eingeführt, um Werte oder Funktionen, die für alle Objekte gemeinsam sind, zu speichern, ohne an eine bestimmte Klasseninstanz gebunden zu sein. Dies ist nützlich für die Speicherung von beispielsweise Zählern, Objektfabriken oder Hilfsfunktionen.
Problem
Eine der Schwierigkeiten war stets der Geltungsbereich und der Zeitpunkt der Initialisierung solcher Mitglieder, insbesondere wenn es in einem Programm viele Quellcodedateien gibt. Eine falsche Definition eines static-Mitglieds führt zu Linkfehlern.
Lösung
In C++ werden statische Mitglieder in der Klassendefinition deklariert, ihre Initialisierung (für Variablen) muss jedoch separat in einer cpp-Datei erfolgen (bis zu C++17). C++17 erlaubt die Initialisierung direkt innerhalb der Deklaration, wenn sie constexpr ist.
Beispielcode:
class MyClass { public: static int counter; static void increment() { ++counter; } }; int MyClass::counter = 0; // Initialisierung ist außerhalb der Klasse erforderlich
Schlüsseleigenschaften:
Was passiert, wenn ein static-Mitglied nicht in der cpp-Datei definiert wird?
Sie erhalten einen Linkfehler, weil die statische Variable deklariert, aber nicht definiert wurde. Ausnahme: wenn static const int direkt innerhalb der Klasse für einen constexpr-Wert initialisiert wird.
// .h class A { public: static int x; }; // .cpp // int A::x = 0; // wenn auskommentiert — wird ein Fehler auftreten
Kann man eine nicht-statische Funktion aus einer statischen aufrufen?
Nein. Der statischen Funktion steht der this-Zeiger und nicht-statische Mitglieder nicht direkt zur Verfügung. Für den Zugriff ist ein konkretes Objekt erforderlich.
class B { int data; static void foo() { // data = 3; // Fehler } };
Sind statische Variablen für alle Instanzen gemeinsam?
Ja, innerhalb einer ausführbaren Datei und eines Prozesses – der gleiche Wert für alle Instanzen.
Im Team wurde vergessen, das static-Mitglied in der cpp-Datei zu definieren, das Projekt wird gelegentlich mit einem Fehler kompiliert, und manchmal tritt bei Verwendung der Inline-Initialisierung (nicht in allen Compilern) ein "mysteriöser" Laufzeitfehler auf.
Vorteile:
Nachteile:
In der Firma gilt die Regel: static-Mitglieder werden immer in cpp-Dateien für jede Klasse definiert. Für Thread-Sicherheit werden std::mutex oder atomare Operationen verwendet.
Vorteile:
Nachteile: