名前空間
変種
操作

ネストしたクラス

提供: 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
メモリ確保
クラス
クラス固有の関数特性
特別なメンバ関数
テンプレート
その他
 
 

class/struct または union の宣言は別のクラス内に現れても構いません。 そのような宣言はネストしたクラスを宣言します。

[編集] 説明

ネストしたクラスの名前は囲っているクラスのスコープに存在し、ネストしたメンバのメンバ関数からの名前探索はネストしたクラスのスコープを調べた後、囲っているクラスのスコープを訪問します。 囲っているクラスのいかなるメンバとも同様に、ネストしたクラスは囲っているクラスがアクセスを持つすべての名前 (プライベートなもの、プロテクテッドなもの、など) へのアクセスを持ちますが、それ以外の点では独立しており、囲っているクラスの this ポインタへの特別なアクセスは持ちません。

ネストしたクラス内の宣言は、囲っているクラスの型名、静的メンバ、および列挙子のみを使用できます。 (C++11未満)

ネストしたクラス内の宣言は、非静的メンバのための通常の使用方法のルールに従って、囲っているクラスのあらゆるメンバを使用できます。

(C++11以上)
int x,y; // グローバル変数。
class enclose { // 囲っているクラス。
    int x; // 注: プライベートメンバ。
    static int s;
 public:
    struct inner { // ネストしたクラス。
        void f(int i) {
            x = i; // エラー、インスタンスなしで非静的メンバ enclose::x に書き込むことはできません。
            int a = sizeof x; // C++11 未満ではエラー。
                              // C++11 では OK。 sizeof の被演算子は未評価であり、
                              // 非静的メンバ enclose::x のこの使用方法は許されます。
            s = i;   // OK、静的メンバ enclose::s に代入できます。
            ::x = i; // OK、グローバル変数 x に代入できます。
            y = i;   // OK、グローバル変数 y に代入できます。
        }
        void g(enclose* p, int i) {
            p->x = i; // OK、 enclose::x への代入。
        }
    };
};

ネストしたクラス内で定義されるフレンド関数は、たとえネストしたクラス内で定義されるメンバ関数の本体からの名前探索が囲っているクラスのプライベートメンバを発見できる場合でも、囲っているクラスのメンバへの特別なアクセスを持ちません。

ネストしたクラスのメンバのクラス外定義は囲っているクラスの名前空間内に現れます。

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

ネストしたクラスは、前方宣言し、後で (同じ囲っているクラス本体内またはその外側のいずれかで) 定義することができます。

class enclose {
    class nested1; // 前方宣言。
    class nested2; // 前方宣言。
    class nested1 {}; // ネストしたクラスの定義。
};
class enclose::nested2 { }; // ネストしたクラスの定義。

ネストしたクラスの宣言はメンバアクセス指定子に従います。 囲っているクラスのスコープの外側でプライベートメンバクラスを表すことはできません (そのクラスのオブジェクトを操作することはできるかもしれませんが)。

class enclose {
    struct nested { // プライベートメンバ。
        void g() {}
    };
 public:
    static nested f() { return nested{}; }
};
 
int main()
{
    //enclose::nested n1 = enclose::f(); // エラー、「nested」はプライベートです。
 
    enclose::f().g(); // OK、「nested」という名前は使っていません。
    auto n2 = enclose::f(); // OK、「nested」という名前は使っていません。
    n2.g();
}

[編集] 参考文献

  • C++11 standard (ISO/IEC 14882:2011):
  • 9.7 Nested class declarations [class.nest]
  • C++98 standard (ISO/IEC 14882:1998):
  • 9.7 Nested class declarations [class.nest]