static
members
クラス定義内では、キーワード static は、クラスのインスタンスに束縛されないメンバーを宣言します。
クラス定義の外側では、異なる意味を持ちます: storage duration を参照してください。
目次 |
構文
静的メンバーの宣言は、宣言指定子にキーワード static を含む メンバー宣言 です。キーワード static は通常、他の指定子の前に現れます(これが構文がしばしば非公式に static data-member または static member-function と記述される理由です)が、指定子シーケンスの任意の場所に現れる可能性があります。
静的データメンバーおよび静的メンバー関数の名前は、それを含むクラスの名前と異ならなければなりません。
説明
クラスの静的メンバは、クラスのオブジェクトに関連付けられていません:これらは静的 またはスレッド (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; // 定義、完全型
|
ただし、宣言が constexpr または inline (C++17以降) 指定子を使用する場合、そのメンバーは完全型を持つように宣言されなければならない。 |
(C++11以降) |
クラスの静的メンバー
m
を参照するには、2つの形式が使用できます:修飾名
T::m
またはメンバーアクセス式
E.m
または
E->m
。ここで
E
はそれぞれ
T
または
T*
に評価される式です。同じクラススコープ内では、修飾は不要です:
struct X { static void f(); // 宣言 static int n; // 宣言 }; X g() { return X(); } // Xを返す関数 void f() { X::f(); // X::fはstaticメンバ関数の修飾名 g().f(); // g().fはstaticメンバ関数を参照するメンバアクセス式 } int X::n = 7; // 定義 void X::f() // 定義 { n = 1; // このスコープではX::nは単にnとしてアクセス可能 }
静的メンバは クラスメンバアクセス規則(private, protected, public) に従います。
静的メンバー関数
静的メンバ関数はどのオブジェクトにも関連付けられていません。呼び出された際、これらは this ポインタを持ちません。
静的メンバー関数は virtual 、 const 、 volatile または ref-qualified にすることはできません。
静的メンバー関数のアドレスは通常の 関数ポインタ に格納できますが、 メンバー関数ポインタ には格納できません。
静的データメンバ
静的データメンバはどのオブジェクトにも関連付けられていません。クラスのオブジェクトが定義されていなくても存在します。静的データメンバのインスタンスはプログラム全体でただ一つであり、静的 ストレージ期間 (キーワード thread_local が使用された場合を除く。その場合はスレッドごとにスレッドストレージ期間を持つオブジェクトが一つ存在する (C++11以降) )を持ちます。
静的データメンバは mutable にできません。
名前空間スコープにおけるクラスの静的データメンバーは、 external linkage を持ちます(クラス自体が external linkage を持つ場合、つまり unnamed namespace のメンバーでない場合)。ローカルクラス(関数内で定義されたクラス)および無名クラス(無名クラスのメンバークラスを含む)は、静的データメンバーを持つことはできません。
|
静的データメンバは 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 ではない)として宣言されている場合、 initializer 内のすべての式が constant expression である初期化子を使用して、クラス定義内で直接初期化することができます:
struct X { const static int n = 1; const static int m{2}; // 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 非インライン (C++17以降) 静的データメンバ またはconstexpr静的データメンバ (C++11以降) (C++17以前) が ODR-use される場合、名前空間スコープでの定義が依然として必要ですが、初期化子を持つことはできません。
|
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 と X::m は ODR-使用されている const int X::n; // … したがって定義が必要 constexpr int X::m; // … (C++17 では X::m を除く)
キーワード
不具合報告
以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。
| DR | 適用対象 | 公開時の動作 | 正しい動作 |
|---|---|---|---|
| CWG 194 | C++98 | (static) member function names can be the same as the class name |
命名制限が追加された(
non-static member functions を含む) |
参考文献
- 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]