static
members
Innerhalb einer Klassendefinition deklariert das Schlüsselwort static Member, die nicht an Klasseninstanzen gebunden sind.
Außerhalb einer Klassendefinition hat es eine andere Bedeutung: siehe storage duration .
Inhaltsverzeichnis |
Syntax
Eine Deklaration für ein statisches Mitglied ist eine Mitgliederdeklaration , deren Deklarationsspezifizierer das Schlüsselwort static enthalten. Das Schlüsselwort static erscheint normalerweise vor anderen Spezifizierern (weshalb die Syntax oft informell als static Datenmitglied oder static Mitgliedsfunktion beschrieben wird), kann aber überall in der Spezifizierer-Sequenz erscheinen.
Der Name jedes statischen Datenelements und jeder statischen Elementfunktion muss sich vom Namen der enthaltenden Klasse unterscheiden.
Erklärung
Statische Member einer Klasse sind nicht mit den Objekten der Klasse assoziiert: Sie sind unabhängige Variablen mit statischer oder Thread- (seit C++11) Speicherdauer oder reguläre Funktionen.
Das static Schlüsselwort wird nur bei der Deklaration eines statischen Members innerhalb der Klassendefinition verwendet, jedoch nicht bei der Definition dieses statischen Members:
class X { static int n; }; // Deklaration (verwendet 'static') int X::n = 1; // Definition (verwendet kein 'static')
Die Deklaration innerhalb des Klassenkörpers ist keine Definition und kann das Mitglied als unvollständigen Typ (außer void ) deklarieren, einschließlich des Typs, in dem das Mitglied deklariert wird:
struct Foo; struct S { static int a[]; // Deklaration, unvollständiger Typ static Foo x; // Deklaration, unvollständiger Typ static S s; // Deklaration, unvollständiger Typ (innerhalb der eigenen Definition) }; int S::a[10]; // Definition, vollständiger Typ struct Foo {}; Foo S::x; // Definition, vollständiger Typ S S::s; // Definition, vollständiger Typ
|
Wenn die Deklaration jedoch constexpr oder inline (seit C++17) Spezifizierer verwendet, muss das Mitglied als vollständiger Typ deklariert werden. |
(seit C++11) |
Um auf ein statisches Mitglied
m
der Klasse
T
zu verweisen, können zwei Formen verwendet werden: qualifizierter Name
T::m
oder Mitgliedszugriffsausdruck
E.m
oder
E->m
, wobei
E
ein Ausdruck ist, der zu
T
oder
T*
ausgewertet wird. Wenn im selben Klassenbereich, ist die Qualifizierung nicht erforderlich:
struct X { static void f(); // Deklaration static int n; // Deklaration }; X g() { return X(); } // eine Funktion, die X zurückgibt void f() { X::f(); // X::f ist ein qualifizierter Name einer statischen Memberfunktion g().f(); // g().f ist ein Memberzugriffsausdruck, der auf eine statische Memberfunktion verweist } int X::n = 7; // Definition void X::f() // Definition { n = 1; // X::n ist in diesem Gültigkeitsbereich als n zugänglich }
Statische Member befolgen die Klassenmember-Zugriffsregeln (private, protected, public) .
Statische Memberfunktionen
Statische Memberfunktionen sind mit keinem Objekt verbunden. Beim Aufruf haben sie keinen this -Zeiger.
Statische Memberfunktionen können nicht virtual , const , volatile oder ref-qualified sein.
Die Adresse eines statischen Member-Funktion kann in einem regulären Zeiger auf Funktion gespeichert werden, aber nicht in einem Zeiger auf Member-Funktion .
Statische Datenelemente
Statische Datenelemente sind mit keinem Objekt assoziiert. Sie existieren selbst dann, wenn keine Objekte der Klasse definiert wurden. Es gibt nur eine Instanz des statischen Datenelements im gesamten Programm mit statischer Speicherdauer , sofern nicht das Schlüsselwort thread_local verwendet wird, in welchem Fall es ein solches Objekt pro Thread mit Thread-Speicherdauer gibt (seit C++11) .
Statische Datenelemente können nicht mutable sein.
Statische Datenelemente einer Klasse im Namensbereich haben externe Bindung wenn die Klasse selbst externe Bindung hat (kein Element eines unbenannten Namensbereichs ist). Lokale Klassen (in Funktionen definierte Klassen) und unbenannte Klassen, einschließlich Memberklassen unbenannter Klassen, können keine statischen Datenelemente haben.
|
Ein statisches Datenelement kann als inline deklariert werden. Ein inline statisches Datenelement kann in der Klassendefinition definiert werden und kann einen Initialisierer angeben. Es benötigt keine Out-of-Class-Definition: struct X { inline static int fully_usable = 1; // No out-of-class definition required, ODR-usable inline static const std::string class_name{"X"}; // Likewise static const int non_addressable = 1; // C.f. non-inline constants, usable // for its value, but not ODR-usable // static const std::string class_name{"X"}; // Non-integral declaration of this // form is disallowed entirely }; |
(seit C++17) |
Konstante statische Member
Wenn ein statisches Datenelement vom integralen oder Aufzählungstyp als const (und nicht volatile ) deklariert wird, kann es mit einem Initialisierer initialisiert werden, in dem jeder Ausdruck ein konstanter Ausdruck ist, direkt innerhalb der Klassendefinition:
struct X { const static int n = 1; const static int m{2}; // seit C++11 const static int k; }; const int X::k = 3;
|
Wenn ein statisches Datenelement von LiteralType als constexpr deklariert wird, muss es mit einem Initialisierer initialisiert werden, in dem jeder Ausdruck ein konstanter Ausdruck ist, direkt innerhalb der Klassendefinition: struct X { constexpr static int arr[] = { 1, 2, 3 }; // OK constexpr static std::complex<double> n = {1,2}; // OK constexpr static int k; // Error: constexpr static requires an initializer }; |
(seit C++11) |
Wenn ein const non-inline (since C++17) static data member oder ein constexpr static data member (since C++11) (until C++17) ODR-used wird, ist weiterhin eine Definition im Namespace-Bereich erforderlich, sie darf jedoch keinen Initialisierer haben.
|
Ein constexpr statisches Datenelement ist implizit inline und muss nicht im Namensbereich neu deklariert werden. Diese Neudeklaration ohne Initialisierer (früher erforderlich) ist weiterhin zulässig, wird jedoch als veraltet eingestuft. |
(since C++17) |
struct X { static const int n = 1; static constexpr int m = 4; }; const int *p = &X::n, *q = &X::m; // X::n und X::m werden ODR-verwendet const int X::n; // … daher ist eine Definition erforderlich constexpr int X::m; // … (außer für X::m in C++17)
Schlüsselwörter
Fehlerberichte
Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | Angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| CWG 194 | C++98 | (static) member function names can be the same as the class name |
Namenseinschränkung hinzugefügt (einschließlich
non-static member functions ) |
Referenzen
- C++23-Standard (ISO/IEC 14882:2024):
-
- 11.4.9 Statische Elemente [class.static]
- C++20-Standard (ISO/IEC 14882:2020):
-
- 11.4.8 Statische Elemente [class.static]
- C++17-Standard (ISO/IEC 14882:2017):
-
- 12.2.3 Statische Elemente [class.static]
- C++14-Standard (ISO/IEC 14882:2014):
-
- 9.4 Statische Elemente [class.static]
- C++11 Standard (ISO/IEC 14882:2011):
-
- 9.4 Statische Elemente [class.static]
- C++98 Standard (ISO/IEC 14882:1998):
-
- 9.4 Statische Elemente [class.static]