
C++での内部クラスの宣言の仕方なのですが、例えば、
class Outer
{
private:
class Inner;
public:
Outer();
~Outer();
};
class Outer::Inner
{
public:
Inner();
~Inner();
};
のように単純に内部クラスが宣言されているだけならば、
その具体的な定義を外側に書くことは可能と思うのですが、
class Outer
{
private:
class Inner
{
public:
Inner();
~Inner();
};
public:
Outer();
~Outer();
Inner inner; //内部クラスのインスタンス
};
のように外部クラスが内部クラスのインスタンスを保持していた場合には、
上記のようにインスタンス作成より上で外部クラスの宣言内に内部クラスの定義を書かないと、
コンパイルが通らない(VC++2008)と思います。具体的な中身がないままインスタンスを
作っているのでエラーを吐く理由もわからないでもないですが、
見易さ的に上の例のようにかけないのかなとも思ったりします。
インスタンスを外部クラスに持たせずともどうとでもなるのですが、
あえて上のようなことをしたくなった場合には下のような方法で記述する以外ないのでしょうか?

No.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は定義できることになります。
すみません。悩んでいたら質問をしたのを忘れてしまいました…。
確かにポインタで確保すればメモリを確保できるのですが、
>スタック(値型)でなくnewヒープを使うことで、いくぶん効率は低下します
を回避するために直接値で保持できないのかなと思いましたが無理みたいですね。
No.2
- 回答日時:
手元にコンパイラがないのでできなかったごめんなさい。
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を多態できるおまけ付きです。
No.1
- 回答日時:
以下のようにすれば、クラス定義を外側に書くどころか、内部クラスの実装を晒さずに済ませることが出来ます。
--- 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;
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Java JavaのSingletonパターンのprivateの持つ意味が分かりません。 5 2022/06/12 10:38
- Java javaのクラスの分け方について質問です。 APIの内部用と外部用でクラスを分けたいのですがインター 2 2022/04/26 16:06
- Java java final 1 2022/06/10 22:49
- Java リレーションエンティティクラスとは何ですか? 2 2023/02/10 00:02
- その他(プログラミング・Web制作) どういうプログラムで組みますか?google colabでやってるんですけど、出来る方お願いします。 1 2022/07/17 18:41
- その他(プログラミング・Web制作) どういうプログラムで組みますか?google colabでやってるんですけど、出来る方お願いします。 1 2022/07/06 09:28
- JavaScript jQueryでのドラッグアンドドロップについて 1 2022/07/30 09:10
- その他(プログラミング・Web制作) このプログラミングをどう組みますか? Googlecolabでやってるんですが、出来る方お願いします 1 2022/07/13 10:52
- PHP アコーディオンPHPが上手くいかない 3 2022/07/15 16:29
- PHP アップロード画像数でCSSを分けることに成功したのですが、画像の横に文字を並べることが出来ません。 3 2023/07/28 17:16
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C#にて別クラスの関数を使いたい
-
親クラスから子クラスへアクセス。
-
そんなにお金がなくても年に1度...
-
今日は こどもの日 で、良い天...
-
EXCEL VBAにて動的にCheckBOXを...
-
DBunitの期待値についての質問...
-
「タイプ初期化子が例外をスロ...
-
0歳児の指しゃぶりに関して
-
BMP画像を画像処理して連続に表...
-
エクセルVBAで、条件に一致する...
-
恋愛
-
DirectXのスプライト機能で3D回転
-
VBAでの[]
-
C++BuilderのMemoコンポーネン...
-
中学生です。 私は教室の黒板に...
-
簡単な説明で結構です
-
ファイル読み込み/書き込み速度...
-
「隣の芝生は青く見える」現象...
-
VBAクラスで、プロパティを使わ...
-
VBA 同じ名前のオブジェクトを...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
クラス間でのデータ参照
-
範囲外の数値を代入したらエラ...
-
関数内の変数に<summary>コメン...
-
C#にて別クラスの関数を使いたい
-
c++,ある関数のクラスから別の...
-
構造 他のクラスの構造体を別...
-
C#でほかのファイルにある自作...
-
C++でfriendクラスにしているの...
-
import と extends について
-
Java リフレクションについて
-
無名パッケージからのインポート
-
visual studioのデザイナ画面で...
-
ひとつのファイルにクラスは1つ?
-
違うクラスからの変数の共有化
-
C#のクラスライブラリでメッセ...
-
継承したクラス側のクラス名の取得
-
Java
-
java-別クラスの変数の使い方を...
-
C# インターフェイスの実装
-
デシリアライズでオブジェクト...
おすすめ情報