[C++] クラス・構造体の前方宣言

2011 年 8 月 1 日

// グローバル領域(名前空間なし)の場合
class Sample;
struct Test;

// 名前空間あり
// 通常のクラス宣言と同じように名前空間の宣言もする必要がある。
namespace example {
	class Sample;
}

// 以下はエラー
class example::Sample;
// exampleクラスのメンバSampleとみなされてしまう。

// typedefされている場合は、
// その元のクラスを先に前方宣言したあとで、
// typedefする必要がある。
class Sample;
typedef Sample NewSample;

// typedefは同じ内容ならば重複定義(記述)しても問題ないが、
// 定義の定義をくり返している場合は、
// そのすべてを前方宣言でtypedefする必要がある。
class Sample;
typedef Sample NewSample;
typedef NewSample ThirdSample;

// 以下のようにすると、エラー。
class Sample;
typedef Sample ThirdSample;
// ThirdSampleに別の定義をしているとみなされる。

// テンプレートクラス
template <class T>
class Sample;

// テンプレートの型のデフォルト引数を前方宣言すると、
// 「既定パラメーターの再定義」と警告が出ることがある。
// 警告を無視するか、実装時に引数の型を明示的に指定するしかない。
// (この辺はコンパイラの実装依存かも)

/* 元の宣言 */
template <class T, class U = int>
class Sample;

/* 前方宣言 */
template <class T, class U = int> // 警告
class Sample;

Sample <char>* sample;

// または
template <class T, class U>
class Sample;

Sample <char , int>* sample;

typedefやテンプレートが複雑にからみ合っていると厄介だが、ひとつひとつベースから前方宣言していくしかない。

なお、STLには<iosfwd>というiostream周りの前方宣言をまとめたヘッダファイルもある。