- ベストアンサー
内部クラスのインスタンスを外部クラスが保持する場合
- C++で内部クラスのインスタンスを外部クラスが保持する場合の書き方について説明します。
- 単純に内部クラスが宣言されている場合は、外部クラスの宣言の後に具体的な定義を書くことができます。
- しかし、外部クラスが内部クラスのインスタンスを保持している場合は、インスタンス作成より上で外部クラスの宣言内に内部クラスの定義を書かなければなりません。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
見やすさ、というよりは、ヘッダの記述量や変更回数を減らしてコンパイル時間を短縮するために前方宣言を使うことはあります。その際、値型でなくポインタ型を使うことになります。 class Outer { public: Outer(); ~Outer(); private: class Inner; Inner* m_pInner; }; // 以下はヘッダでなく実装ファイルに記述する。 class Outer::Inner { public: Inner(); ~Inner(); }; Outer::Outer() : m_pInner() { m_pInner = new Outer::Inner(); } Outer::~Outer() { delete m_pInner; } スタック(値型)でなくnewヒープを使うことで、いくぶん効率は低下します。また、ヒープの解放忘れといったヒープ特有のバグが混入しないように気をつける必要があります。 Innerの詳細が分からない段階で値型として埋め込むことができないのは、コンパイラにとってOuterの定義に必要なsizeof(Inner)の計算が実行できないからです。ポインタであればInnerがどのような型であれsizeof(Inner*)は常に一定(ILP32で4バイト、LP64/LLP64で8バイト)のため、前方宣言さえあればOuterは定義できることになります。
その他の回答 (2)
- tsuduki123
- ベストアンサー率32% (21/65)
手元にコンパイラがないのでできなかったごめんなさい。 class Outer: class Outer::Inner; class Outer { public: Outer(void){; } virtual ~Outer(void){ ; } private: Inner Inner; } class Outer::Inner { private: Inner(void){ ; } virtual Inner(void){ ; } protected: Inner(const inner &in){ ; } } って感じに、プロトタイプ的なものを宣言してあげればすむと思うけれど 個人的には、 へんなことせず、使う順に宣言されていた方がわかりやすいと思いますよ。 # つまり、後者(?)の書き方。 ちなみに、 コンストラクタでは、代入以外しないほうがいいです。 とくに、メモリ確保などは失敗したときのハンドリングができないので異常系処理が面倒になります。 たぶんやるなら class Inner { } class Outer { public: Outer(inner &in) : inner(in) { ; } private: Inner &inner } とかじゃなかったかな? こうすると Innerを多態できるおまけ付きです。
- hitomura
- ベストアンサー率48% (325/664)
以下のようにすれば、クラス定義を外側に書くどころか、内部クラスの実装を晒さずに済ませることが出来ます。 --- Outer.h --- class Outer { private: class Inner; Inner* inner; // クラスのインスタンスそのものではなくポインタを持つ public: Outer(void); ~Outer(void); }; --- Outer.cpp --- #include "Outer.h" class Outer::Inner { public: Inner() {}; ~Inner(){}; }; Outer::Outer(void) : inner(new Inner) { } Outer::~Outer(void) { if (inner != 0) delete inner; }
お礼
すみません。悩んでいたら質問をしたのを忘れてしまいました…。 確かにポインタで確保すればメモリを確保できるのですが、 >スタック(値型)でなくnewヒープを使うことで、いくぶん効率は低下します を回避するために直接値で保持できないのかなと思いましたが無理みたいですね。