名前空間
変種
操作

入れ子クラス

From cppreference.com
< cpp‎ | language
 
 
C++言語
全般
フロー制御
条件実行文
if
繰り返し文 (ループ)
for
範囲for (C++11)
ジャンプ文
関数
関数宣言
ラムダ式
inline指定子
動的例外仕様 (C++17まで*)
noexcept指定子 (C++11)
例外
名前空間
指定子
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点数
文字 - 文字列 - nullptr (C++11)
ユーザー定義 (C++11)
ユーティリティ
属性 (C++11)
typedef宣言
型エイリアス宣言 (C++11)
キャスト
メモリ確保
クラス
クラス固有の関数プロパティ
explicit (C++11)
static

特殊メンバ関数
テンプレート
その他
 
 

クラス/構造体または共用体の宣言は、別のクラス内に現れることがあります。このような宣言は、入れ子クラスを宣言します。

[編集] 解説

入れ子クラスの名前は、外側のクラスのスコープ内に存在し、入れ子クラスのメンバー関数からの名前探索は、入れ子クラスのスコープを調べた後、外側のクラスのスコープを訪れます。外側のクラスの他のメンバーと同様に、入れ子クラスは外側のクラスがアクセスできるすべての名前(private、protectedなど)にアクセスできますが、それ以外は独立しており、外側のクラスのthisポインターへの特別なアクセス権はありません。入れ子クラス内の宣言は、非静的メンバーの通常の利用規則に従って、外側のクラスの任意のメンバーを使用できます。

int x, y; // globals
class enclose // enclosing class
{
    // note: private members
    int x;
    static int s;
public:
    struct inner // nested class
    {
        void f(int i)
        {
            x = i; // Error: can't write to non-static enclose::x without instance
            int a = sizeof x; // Error until C++11,
                              // OK in C++11: operand of sizeof is unevaluated,
                              // this use of the non-static enclose::x is allowed.
            s = i;   // OK: can assign to the static enclose::s
            ::x = i; // OK: can assign to global x
            y = i;   // OK: can assign to global y
        }
 
        void g(enclose* p, int i)
        {
            p->x = i; // OK: assign to enclose::x
        }
    };
};

入れ子クラス内で定義されたフレンド関数は、入れ子クラス内で定義されたメンバー関数の本体からの探索が外側のクラスのプライベートメンバーを見つけることができる場合でも、外側のクラスのメンバーに特別なアクセス権はありません。

入れ子クラスのメンバーのクラス外定義は、外側のクラスの名前空間に現れます。

struct enclose
{
    struct inner
    {
        static int x;
        void f(int i);
    };
};
 
int enclose::inner::x = 1;       // definition
void enclose::inner::f(int i) {} // definition

入れ子クラスは、同じ外側のクラスの本体内でも、その外側でも、前方宣言され、後で定義することができます。

class enclose
{
    class nested1;    // forward declaration
    class nested2;    // forward declaration
    class nested1 {}; // definition of nested class
};
 
class enclose::nested2 {}; // definition of nested class

入れ子クラスの宣言はメンバーアクセス指定子に従います。プライベートなメンバークラスは、そのクラスのオブジェクトを操作できる場合でも、外側のクラスのスコープ外では名前で指定できません。

class enclose
{
    struct nested // private member
    {
        void g() {}
    };
public:
    static nested f() { return nested{}; }
};
 
int main()
{
    //enclose::nested n1 = enclose::f(); // error: 'nested' is private
 
    enclose::f().g();       // OK: does not name 'nested'
    auto n2 = enclose::f(); // OK: does not name 'nested'
    n2.g();
}

[編集] 欠陥報告

以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。

DR 適用対象 公開された動作 正しい動作
CWG 45 C++98 入れ子クラスのメンバーは
外側のクラスとそのフレンドにアクセスできません。
それらは他の
外側のクラスのメンバーと同じアクセス権を持ちます。
(CWG の問題 #8 および #10 も解決します)

[編集] 参照

  • C++23標準 (ISO/IEC 14882:2024)
  • 11.4.12 入れ子クラスの宣言 [class.nest]
  • C++20 standard (ISO/IEC 14882:2020)
  • 11.4.10 入れ子クラスの宣言 [class.nest]
  • C++17 standard (ISO/IEC 14882:2017)
  • 12.2.5 入れ子クラスの宣言 [class.nest]
  • C++14 standard (ISO/IEC 14882:2014)
  • 9.7 入れ子クラスの宣言 [class.nest]
  • C++11 standard (ISO/IEC 14882:2011)
  • 9.7 入れ子クラスの宣言 [class.nest]
  • C++98 標準 (ISO/IEC 14882:1998)
  • 9.7 入れ子クラスの宣言 [class.nest]
English 日本語 中文(简体) 中文(繁體)