static
members
在类定义内部,关键字 static 用于声明不绑定到类实例的成员。
在类定义之外,它具有不同的含义:参见 存储期 。
目录语法静态成员的声明是一种成员声明,其声明说明符包含关键字 任何静态数据成员和静态成员函数的名称必须与包含类的名称不同。 说明类的静态成员不与类的对象相关联:它们是具有静态 或线程 (since 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; // 定义,完整类型
要引用类
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; // 在此作用域中可直接以 n 访问 X::n } 静态成员遵循 类成员访问规则(private、protected、public) 。 静态成员函数静态成员函数不与任何对象关联。当被调用时,它们没有 this 指针。 静态成员函数不能是 virtual 、 const 、 volatile 或 引用限定 的。 静态成员函数的地址可以存储在常规的 函数指针 中,但不能存储在 成员函数指针 中。 静态数据成员静态数据成员不与任何对象关联。即使尚未定义类的对象,它们也存在。整个程序中只有一个具有静态 存储期的静态数据成员实例,除非使用了关键字 thread_local,在这种情况下每个线程拥有一个具有线程存储期的此类对象(自 C++11 起)。 静态数据成员不能是 命名空间作用域中的类的静态数据成员具有外部链接,如果该类本身具有外部链接(不是无名命名空间的成员)。局部类(在函数内部定义的类)和无名类(包括无名类的成员类)不能有静态数据成员。
常量静态成员如果整型或枚举类型的静态数据成员被声明为 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;
如果 const 非内联 (C++17 起) 静态数据成员 或 constexpr 静态数据成员 (C++11 起) (C++17 前) 被 ODR 使用 ,仍需要在命名空间作用域提供定义,但该定义不能包含初始化器。
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; // …(C++17 中 X::m 除外) 关键词缺陷报告以下行为变更缺陷报告被追溯应用于先前发布的C++标准。
参考文献
参见 |