Namespaces
Variants

static members

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
explicit (C++11)
static

Special member functions
Templates
Miscellaneous

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

クラス定義の外側では、異なる意味を持ちます: storage duration を参照してください。

目次

翻訳のポイント: - HTMLタグ、属性、数値はそのまま保持 - C++専門用語(Static member functions、Static data members、Constant static members)は翻訳せず保持 - 一般的な用語のみ日本語に翻訳 - フォーマットと構造は完全に維持

構文

静的メンバーの宣言は、宣言指定子にキーワード 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 を除く)

キーワード

static

不具合報告

以下の動作変更の欠陥報告書は、以前に公開された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]

関連項目