入れ子クラス
From cppreference.com
クラス/構造体または共用体の宣言は、別のクラス内に現れることがあります。このような宣言は、入れ子クラスを宣言します。
[編集] 解説
入れ子クラスの名前は、外側のクラスのスコープ内に存在し、入れ子クラスのメンバー関数からの名前探索は、入れ子クラスのスコープを調べた後、外側のクラスのスコープを訪れます。外側のクラスの他のメンバーと同様に、入れ子クラスは外側のクラスがアクセスできるすべての名前(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]