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 起) |
要引用类 T
的静态成员 m
,可以使用两种形式:限定名称 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 }
静态成员遵循 类成员访问规则 (私有、受保护、公共).
[编辑] 静态成员函数
静态成员函数与任何对象无关。当调用时,它们没有 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)
[编辑] 关键字
[编辑] 缺陷报告
以下更改行为的缺陷报告已追溯应用于以前发布的 C++ 标准。
DR | 应用于 | 已发布的行为 | 正确行为 |
---|---|---|---|
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]