static члены
Внутри определения класса ключевое слово static объявляет члены, которые не привязаны к экземплярам класса.
Вне определения класса оно имеет другое значение: см. срок хранения.
Синтаксис
Объявление статического члена — это объявление члена, в спецификаторах объявления которого содержится ключевое слово static. Ключевое слово static обычно появляется перед другими спецификаторами (поэтому синтаксис часто описывается неформально как static данные члена или static функция-член), но может появиться в любом месте последовательности спецификаторов.
Имя любого статического данных члена и статической функции-члена должно отличаться от имени содержащего класса.
Объяснение
Статические члены класса не связаны с объектами класса: они являются независимыми переменными со статическим или потоковым(с C++11) сроком хранения или обычными функциями.
Ключевое слово static используется только с объявлением статического члена внутри определения класса, но не с определением этого статического члена:
class X { static int n; }; // declaration (uses 'static')
int X::n = 1; // definition (does not use 'static')Объявление внутри тела класса не является определением и может объявлять член как неполного типа неполного типа (кроме void), включая тип, в котором объявлен член:
struct Foo;
struct S
{
static int a[]; // declaration, incomplete type
static Foo x; // declaration, incomplete type
static S s; // declaration, incomplete type (inside its own definition)
};
int S::a[10]; // definition, complete type
struct Foo {};
Foo S::x; // definition, complete type
S S::s; // definition, complete type|
Однако, если объявление использует |
(с C++11) |
Для ссылки на статический член m класса T, могут использоваться два формата: квалифицированное имя T::m или выражение доступа к члену E.m или E->m, где E — выражение, вычисляющее T или T* соответственно. В пределах того же области видимости класса квалификация не требуется:
struct X
{
static void f(); // declaration
static int n; // declaration
};
X g() { return X(); } // some function returning X
void f()
{
X::f(); // X::f is a qualified name of static member function
g().f(); // g().f is member access expression referring to a static member function
}
int X::n = 7; // definition
void X::f() // definition
{
n = 1; // X::n is accessible as just n in this scope
}Статические члены подчиняются правилам доступа к членам класса (private, protected, public).
Статические функции-члены
Статические функции-члены не связаны ни с каким объектом. При вызове у них нет указателя this.
Статические функции-члены не могут быть virtual, const, volatile, или ссылочно-квалифицированными.
Адрес статической функции-члена может быть сохранен в обычном указателе на функцию, но не в указателе на функцию-член.
Статические данные членов
Статические данные члены не связаны ни с каким объектом. Они существуют даже если не определены объекты класса. Существует только один экземпляр статического данных члена во всей программе со статическим сроком хранения, если не используется ключевое слово thread_local, в этом случае такой объект существует в каждом потоке с потоковым сроком хранения(с C++11).
Статические данные члены не могут быть mutable.
Статические данные члены класса в области видимости пространства имен имеют внешнюю связь, если сам класс имеет внешнюю связь (не является членом безымянного пространства имен). Локальные классы (классы, определенные внутри функций) и безымянные классы, включая вложенные классы безымянных классов, не могут иметь статические данные члены.
|
Статический данных член может быть объявлен struct X
{
inline static int n = 1;
}; |
(с C++17) |
Постоянные статические члены
Если статический данных член целочисленного или перечислимого типа объявлен const (и не volatile), его можно инициализировать инициализатором, в котором каждое выражение является константным выражением, непосредственно внутри определения класса:
struct X
{
const static int n = 1;
const static int m{2}; // since C++11
const static int k;
};
const int X::k = 3;|
Если статический данных член типа LiteralType объявлен 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) |
Если const не-встроенный(с C++17) статический данных член или constexpr статический данных член(с C++11)(до C++17) используется в ODR-использовании, определение в области видимости пространства имен всё ещё требуется, но оно не может иметь инициализатор.
|
|
(с C++17) |
struct X
{
static const int n = 1;
static constexpr int m = 4;
};
const int *p = &X::n, *q = &X::m; // X::n and X::m are odr-used
const int X::n; // … so a definition is necessary
constexpr int X::m; // … (except for X::m in C++17)Отчеты об ошибках
Следующие отчеты об ошибках, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Применено к | Поведение, как опубликовано | Правильное поведение |
|---|---|---|---|
| CWG 194 | C++98 | (статические) имена функций-членов могут быть такими же, как у класса | Добавлена ограничение на именование (включая нестатические функции-члены) |
Ссылки
- Стандарт C++23 (ISO/IEC 14882:2023):
- 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]
См. также
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/language/static