Spec-Zone.ru › C++

static члены

В определении класса ключевое слово static объявляет члены, не связанные с экземплярами класса.

Вне определения класса оно имеет другое значение: см. длительность хранения.

Синтаксис

Объявление статического члена — это объявление члена, в спецификаторах объявления которого содержится ключевое слово static. Ключевое слово static обычно располагается перед другими спецификаторами (поэтому синтаксис часто неформально описывают как static member-declaration), но может находиться в любом месте последовательности спецификаторов.

Имя любого статического члена данных и любой статической функции-члена должно отличаться от имени содержащего их класса.

Пояснение

Статические члены класса не связаны с объектами этого класса: это независимые переменные со статической или потоковой(начиная с 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

Однако если в объявлении используется спецификатор constexpr или inline(начиная с C++17), член должен быть объявлен с полным типом.

(начиная с 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.

Статические члены данных класса в области видимости пространства имён имеют внешнее связывание, если сам класс имеет внешнее связывание (то есть не является членом безымянного пространства имён). Локальные классы (классы, определённые внутри функций) и безымянные классы, включая классы-члены безымянных классов, не могут иметь статических членов данных.

Статический член данных может быть объявлен 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}; // since 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)

Если константный статический член данных, не являющийся встроенным,(начиная с C++17) или статический член данных constexpr(начиная с C++11)(до C++17) используется по ODR, определение в области видимости пространства имён по-прежнему требуется, но оно не может содержать инициализатор.

Статический член данных constexpr неявно является inline, и его не нужно повторно объявлять в области видимости пространства имён. Такое повторное объявление без инициализатора (ранее обязательное) по-прежнему разрешено, но считается устаревшим.

(начиная с 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)

Ключевые слова

static

Отчёты об ошибках

Следующие отчёты об ошибках, изменяющие поведение, были применены задним числом к ранее опубликованным стандартам C++.

Отчёт об ошибке Применяется к Поведение согласно опубликованному стандарту Исправленное поведение
CWG 194 C++98 имена функций-членов (static) могут совпадать с именем класса добавлено ограничение на имена (в том числе для
нестатических функций-членов)

Ссылки

  • Стандарт 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]

См. также

  • Спецификатор static хранения

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/static

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API