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 }
靜態成員遵循類成員訪問規則(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 起) |
如果 const 非 inline(C++17 起) 靜態資料成員或 constexpr 靜態資料成員(C++11 起)(C++17 前) 是ODR-used,仍需要在名稱空間作用域提供定義,但它不能帶有初始化器。
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++ 標準。
缺陷報告 | 應用於 | 釋出時的行為 | 正確的行為 |
---|---|---|---|
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]