名前空間
変種
操作

静的メンバ

提供: cppreference.com
< cpp‎ | language
 
 
C++言語
一般的なトピック
フロー制御
条件付き実行文
繰り返し文 (ループ)
ジャンプ文
関数
関数宣言
ラムダ関数宣言
inline 指定子
例外指定 (C++20未満)
noexcept 指定子 (C++11)
例外
名前空間
指定子
decltype (C++11)
auto (C++11)
alignas (C++11)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点
文字 - 文字列 - nullptr (C++11)
ユーザ定義 (C++11)
ユーティリティ
属性 (C++11)
typedef 宣言
型エイリアス宣言 (C++11)
キャスト
暗黙の変換 - 明示的な変換
static_cast - dynamic_cast
const_cast - reinterpret_cast
メモリ確保
クラス
クラス固有の関数特性
explicit (C++11)
static
特別なメンバ関数
テンプレート
その他
 
 

クラス定義の内側では、キーワード static はクラスのインスタンスに束縛されないメンバを宣言します。

クラス定義の外側では、キーワード static は別の意味を持ちます。 記憶域期間を参照してください。

目次

[編集] 構文

static data_member (1)
static member_function (2)
1) 静的データメンバを宣言します。
2) 静的メンバ関数を宣言します。

[編集] 説明

クラスの静的メンバはクラスのオブジェクトに紐付けられません。 それらは静的またはスレッド (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以上)

クラス T の静的メンバ m を参照するためには、修飾された名前 T::m またはメンバアクセス式 E.m または E->m の2つの形式が使用できます。 ただし E はそれぞれ T または T* に評価される式です。 同じクラススコープ内のときは、修飾は不要です。

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; // X::n はこのスコープ内では単に n としてアクセス可能です。
}

静的メンバはクラスメンバのアクセスルール (private、 protected、 public) に従います。

[編集] 静的メンバ関数

静的メンバ関数はいかなるオブジェクトにも紐付けられません。 呼ばれたとき、 this ポインタはありません。

静的メンバ関数は virtualconstvolatile にできません。

静的メンバ関数のアドレスは普通の関数へのポインタに格納できますが、メンバ関数へのポインタには格納できません。

[編集] 静的データメンバ

静的データメンバはいかなるオブジェクトにも紐付けられません。 これらはたとえそのクラスのオブジェクトが定義されなくても存在します。 静的データメンバのインスタンスはプログラム全体でひとつだけ存在し、静的記憶域期間を持ちます。 ただしキーワード thread_local が使用された場合は異なり、その場合はスレッドごとにひとつのオブジェクトが存在し、スレッド記憶域期間を持ちます。 (C++11以上)

静的データメンバは mutable にできません。

名前空間スコープのクラスの静的データメンバは、そのクラス自身が外部リンケージを持つ (すなわち無名名前空間のメンバでない) 場合は、外部リンケージを持ちます。 ローカルクラス (関数内で定義されたクラス) および無名クラス (無名クラスのメンバクラスを含みます) は静的データメンバを持つことができません。

静的データメンバは inline 宣言することもできます。 インライン静的データメンバはクラス定義内で定義でき、初期化子を指定することもできます。 インライン静的データメンバはクラスの外側での定義を必要としません。

struct X
{
    inline static int n = 1;
};
(C++17以上)

[編集] 定数静的メンバ

整数型または列挙型の静的データメンバが 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;

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; // エラー、 constexpr static は初期化子が必要です。
};
(C++11以上)

const 非 inline (C++17以上) 静的データメンバまたは constexpr 静的データメンバ (C++11以上)ODR 使用される場合、名前空間スコープの定義は未だ必要ですが、初期化子を持つことはできません。 この定義は constexpr データメンバに対しては非推奨です。 (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 については不要です。)

静的データメンバが constexpr 宣言される場合、それは暗黙に inline であり、名前空間スコープで再宣言する必要はありません。 初期化子なしのこの再宣言 (上に示した通り形式的に要求されます) は未だ許さていれますが、非推奨です。

(C++17以上)

[編集] 参考文献

  • C++11 standard (ISO/IEC 14882:2011):
  • 9.4 Static members [class.static]
  • C++98 standard (ISO/IEC 14882:1998):
  • 9.4 Static members [class.static]

[編集] 関連項目