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;
如果 字面类型 的静态数据成员被声明为 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 起) |
如果 const 非内联(自 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 | (静态)成员函数名称可以与类名称相同 | 添加命名限制(包括 非静态成员函数) |
[编辑] 参考文献
- 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]