Nested classes
| 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 | ||||||||||||||||
|
||||||||||||||||
| 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 | ||||||||||||||||
|
||||||||||||||||
| Special member functions | ||||||||||||||||
|
||||||||||||||||
| Templates | ||||||||||||||||
| Miscellaneous | ||||||||||||||||
クラス/構造体または共用体の宣言は、他のクラス内に現れることがあります。そのような宣言は ネストされたクラス を宣言します。
説明
ネストされたクラスの名前は、外側のクラスのスコープ内に存在し、ネストされたクラスのメンバー関数からの名前探索は、ネストされたクラスのスコープを調べた後、外側のクラスのスコープを参照します。外側のクラスの任意のメンバーと同様に、ネストされたクラスは外側のクラスがアクセス可能なすべての名前(private、protectedなど)にアクセスできますが、それ以外は独立しており、外側のクラスの
this
pointer
への特別なアクセス権はありません。ネストされたクラス内の宣言では、非静的メンバーに対する
通常の使用規則
に従って、外側のクラスのあらゆるメンバーを使用できます。
int x, y; // グローバル変数 class enclose // 外側のクラス { // 注: privateメンバ int x; static int s; public: struct inner // ネストされたクラス { void f(int i) { x = i; // エラー: インスタンスなしでは非staticなenclose::xに書き込めない int a = sizeof x; // C++11までエラー、 // C++11ではOK: sizeofのオペランドは評価されないため、 // 非staticなenclose::xのこの使用は許可される s = i; // OK: staticなenclose::sに代入可能 ::x = i; // OK: グローバルxに代入可能 y = i; // OK: グローバルyに代入可能 } void g(enclose* p, int i) { p->x = i; // OK: enclose::xに代入 } }; };
Friend ネストされたクラス内で定義されたフレンド関数は、たとえネストされたクラス内で定義されたメンバー関数の本体からのルックアップが外側のクラスのプライベートメンバーを見つけることができる場合でも、外側のクラスのメンバーに対する特別なアクセス権を持ちません。
ネストされたクラスのメンバーのクラス外定義は、外側のクラスの名前空間内に現れます:
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 {}; // ネストされたクラスの定義
ネストされたクラス宣言は メンバーアクセス 指定子に従います。privateメンバークラスは、外側のクラスのスコープ外では名前を参照できませんが、そのクラスのオブジェクトを操作することは可能です:
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++規格に対して遡及的に適用されました。
| DR | 適用対象 | 公開時の動作 | 正しい動作 |
|---|---|---|---|
| CWG 45 | C++98 |
ネストされたクラスのメンバーは
外側のクラスとそのフレンドにアクセスできない |
外側のクラスの他のメンバーと同じ
アクセス権を持つ (CWG 問題 #8 および #10 も解決) |
参考文献
- C++23規格 (ISO/IEC 14882:2024):
-
- 11.4.12 ネストされたクラス宣言 [class.nest]
- C++20 標準 (ISO/IEC 14882:2020):
-
- 11.4.10 ネストされたクラス宣言 [class.nest]
- C++17規格 (ISO/IEC 14882:2017):
-
- 12.2.5 ネストされたクラス宣言 [class.nest]
- C++14標準 (ISO/IEC 14882:2014):
-
- 9.7 ネストしたクラス宣言 [class.nest]
- C++11標準 (ISO/IEC 14882:2011):
-
- 9.7 ネストしたクラス宣言 [class.nest]
- C++98標準 (ISO/IEC 14882:1998):
-
- 9.7 ネストしたクラス宣言 [class.nest]