static 成員
在類別定義內部,關鍵字 static 用於宣告不綁定至類別實例(instance)的成員。
在類別定義外部,它具有不同的意義:請參閱 儲存期 (storage duration)。
目錄 |
[編輯] 語法
靜態成員的宣告是一種 成員宣告,其宣告說明符包含關鍵字 static。關鍵字 static 通常出現在其他說明符之前(這就是為什麼語法通常被非正式地描述為 static 資料成員 或 static 成員函式),但它可以出現在說明符序列中的任何位置。
任何靜態資料成員和靜態成員函式的名稱,必須與包含它的類別名稱不同。
[編輯] 解釋
類別的靜態成員與該類別的物件無關:它們是具有靜態或執行緒 (thread)(C++11 起) 儲存期的獨立變數,或是普通函式。
static 關鍵字僅在類別定義內部的靜態成員宣告時使用,在該靜態成員的定義處則不可使用。
class X { static int n; }; // declaration (uses 'static') int X::n = 1; // definition (does not use 'static')
類別主體內的宣告並非定義,且可以宣告該成員為 不完整型別 (incomplete type)(除了 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 或具有 引用限定 (ref-qualified)。
靜態成員函式的位址可以儲存在普通的 函式指標 中,但不能儲存在 成員函式指標 中。
[編輯] 靜態資料成員
靜態資料成員與任何物件無關。即使未定義該類別的任何物件,它們也存在。在整個程式中,靜態資料成員只有一個實例,且具有靜態 儲存期,除非使用了關鍵字 thread_local,在此情況下,每個執行緒會有一個具有執行緒儲存期的該物件(C++11 起)。
靜態資料成員不能是 mutable。
若類別本身具有外部連結(非 未命名命名空間 的成員),則位於命名空間作用域的類別之靜態資料成員具有 外部連結。區域類別(在函式內部定義的類別)和未命名類別(包含未命名類別的成員類別)不能擁有靜態資料成員。
|
靜態資料成員可以宣告為 inline。內聯(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 非內聯 (non-inline)(C++17 起) 靜態資料成員 或一個 constexpr 靜態資料成員(C++11 起)(C++17 前) 被 ODR-使用 (ODR-use),則仍然需要在命名空間作用域提供定義,但該定義不能包含初始值設定項。
|
一個 constexpr 靜態資料成員是隱式 inline 的,不需要在命名空間作用域重新宣告。這種不帶初始值設定項的重新宣告(舊版 C++ 曾要求)仍然被允許,但已棄用。 |
(自 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 Static members [class.static]
- C++20 標準 (ISO/IEC 14882:2020)
- 11.4.8 Static members [class.static]
- C++17 標準 (ISO/IEC 14882:2017)
- 12.2.3 Static members [class.static]
- C++14 標準 (ISO/IEC 14882:2014)
- 9.4 Static members [class.static]
- C++11 標準 (ISO/IEC 14882:2011)
- 9.4 Static members [class.static]
- C++98 標準 (ISO/IEC 14882:1998)
- 9.4 Static members [class.static]