static
members
Внутри определения класса ключевое слово static объявляет члены, которые не привязаны к экземплярам класса.
Вне определения класса это имеет другое значение: см. storage duration .
Содержание |
Синтаксис
Объявление для статического члена является объявлением члена , спецификаторы объявления которого содержат ключевое слово static . Ключевое слово static обычно появляется перед другими спецификаторами (поэтому синтаксис часто неформально описывается как static data-member или static member-function ), но может появляться в любом месте последовательности спецификаторов.
Имя любого статического члена данных и статической функции-члена должно отличаться от имени содержащего класса.
Объяснение
Статические члены класса не связаны с объектами класса: они являются независимыми переменными со статической или поточной (начиная с C++11) продолжительностью хранения или обычными функциями.
Ключевое слово static используется только при объявлении статического члена внутри определения класса, но не при определении этого статического члена:
class X { static int n; }; // объявление (использует 'static') int X::n = 1; // определение (не использует 'static')
Объявление внутри тела класса не является определением и может объявлять член как неполный тип (кроме void ), включая тип, в котором объявлен член:
struct Foo; struct S { static int a[]; // объявление, неполный тип static Foo x; // объявление, неполный тип static S s; // объявление, неполный тип (внутри собственного определения) }; int S::a[10]; // определение, полный тип struct Foo {}; Foo S::x; // определение, полный тип S S::s; // определение, полный тип
|
Однако, если объявление использует constexpr или inline (начиная с C++17) спецификатор, член должен быть объявлен с полным типом. |
(начиная с C++11) |
Для обращения к статическому члену
m
класса
T
могут использоваться две формы: квалифицированное имя
T::m
или выражение доступа к члену
E.m
или
E->m
, где
E
является выражением, которое вычисляется в
T
или
T*
соответственно. Когда обращение происходит в той же области видимости класса, квалификация не требуется:
struct X { static void f(); // объявление static int n; // объявление }; X g() { return X(); } // некоторая функция, возвращающая X void f() { X::f(); // X::f - квалифицированное имя статической функции-члена g().f(); // g().f - выражение доступа к члену, ссылающееся на статическую функцию-член } int X::n = 7; // определение void X::f() // определение { n = 1; // X::n доступен как просто n в этой области видимости }
Статические члены подчиняются правилам доступа к членам класса (private, protected, public) .
Статические функции-члены
Статические функции-члены не связаны с каким-либо объектом. При вызове у них отсутствует this указатель.
Статические функции-члены не могут быть virtual , const , volatile , или ref-qualified .
Адрес статической функции-члена может быть сохранён в обычном указателе на функцию , но не в указателе на функцию-член .
Статические члены данных
Статические члены данных не связаны с каким-либо объектом. Они существуют, даже если не определены объекты класса. В программе существует только один экземпляр статического члена данных со статической продолжительностью хранения , если не используется ключевое слово thread_local , в этом случае существует один такой объект на поток с продолжительностью хранения потока (начиная с C++11) .
Статические члены данных не могут быть mutable .
Статические члены данных класса в области видимости пространства имён имеют внешнюю линковку , если сам класс имеет внешнюю линковку (не является членом безымянного пространства имён ). Локальные классы (классы, определённые внутри функций) и безымянные классы, включая классы-члены безымянных классов, не могут иметь статических членов данных.
|
Статический член данных может быть объявлен inline . Встроенный статический член данных может быть определен в определении класса и может указывать инициализатор. Он не требует внешнего определения: 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 }; |
(начиная с C++17) |
Константные статические члены
Если статический элемент данных целочисленного или перечислимого типа объявлен const (и не volatile ), он может быть инициализирован с помощью инициализатора , в котором каждое выражение является константным выражением , непосредственно внутри определения класса:
struct X { const static int n = 1; const static int m{2}; // начиная с C++11 const static int k; }; const int X::k = 3;
|
Если статический член данных LiteralType объявлен как constexpr , он должен быть инициализирован инициализатором, в котором каждое выражение является константным выражением, непосредственно внутри определения класса: 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 }; |
(начиная с C++11) |
Если константный не-inline (since C++17) статический член данных или constexpr статический член данных (since C++11) (until C++17) подвергается ODR-использованию , определение в области видимости пространства имён всё ещё требуется, но оно не может иметь инициализатора.
|
Статический элемент данных constexpr является неявно inline и не требует повторного объявления в области видимости пространства имен. Такое повторное объявление без инициализатора (ранее требовавшееся) всё ещё разрешено, но считается устаревшим. |
(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 и X::m являются ODR-используемыми const int X::n; // … поэтому определение необходимо constexpr int X::m; // … (кроме X::m в C++17)
Ключевые слова
Отчеты о дефектах
Следующие отчеты об изменениях в поведении, являющиеся дефектными, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| CWG 194 | C++98 | имена (статических) функций-членов могут совпадать с именем класса |
добавлено ограничение на именование (включая
нестатические функции-члены ) |
Ссылки
- Стандарт C++23 (ISO/IEC 14882:2024):
-
- 11.4.9 Статические члены [class.static]
- Стандарт C++20 (ISO/IEC 14882:2020):
-
- 11.4.8 Статические члены [class.static]
- Стандарт C++17 (ISO/IEC 14882:2017):
-
- 12.2.3 Статические члены [class.static]
- Стандарт C++14 (ISO/IEC 14882:2014):
-
- 9.4 Статические члены [class.static]
- Стандарт C++11 (ISO/IEC 14882:2011):
-
- 9.4 Статические члены [class.static]
- Стандарт C++98 (ISO/IEC 14882:1998):
-
- 9.4 Статические члены [class.static]