103
88

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【C++】クラスの前方宣言まとめ

Last updated at Posted at 2016-05-23

C++において、余計なinlucdeを減らすためにクラスの前方宣言を利用することは、基本的なテクニックだと思います。ただ、何もないシンプルなクラスの前方宣言ならまだしも、実際には名前空間があったり、templateだったりするクラスも普通に存在します。そのたびに、前方宣言の書き方を確認するのは無駄な時間なので、まとめておきます。

以下は、前方前言を記述するクラスのヘッダファイルのみを示します
(定義部分等はなくても大体予想がつくと思うので、あくまでも前方宣言にフォーカスします)。

普通の前方宣言

ごく一般的な前方宣言です。

普通の前方宣言(ClassAのメンバ変数としてClassBを持つ場合)
class classB;
class classA
{
public:
	classA();
	~classA();
private:
	classB *objB;
};

名前空間がある場合の前方宣言

メンバ変数にしたいクラスが名前空間で囲まれていたら、下記のようにします。

名前空間がある場合の前方宣言ClassAのメンバ変数としてClassCを持つ場合)
namespace NS_C{
	class classC;
}
class classA
{
public:
	classA();
	~classA();
private:
	NS_C::classC *objC;
};

typedefされているクラスの前方宣言

メンバ変数にしたいクラスがtypdefされている場合は、同じようにtypdefしてあげます。

typedefがある場合の前方宣言ClassAのメンバ変数としてClassDDを持つ場合)
class classD;
typedef classD classDD;
class classA
{
public:
	classA();
	~classA();
private:
	classDD *objD;
};

usingされている場合の前方宣言

C++11以降では、積極的にusingが使われるようになると思いますが、そのような場合もtypdefと同じように、usingを書いてあげます。

using(C++11以降)がある場合の前方宣言ClassAのメンバ変数としてClassEEを持つ場合)
class classE;
using classEE = classE;
class classA
{
public:
	classA();
	~classA();
private:
	classEE *objE;
};

テンプレートクラスの前方宣言

テンプレートクラスの場合は下記のように書きますが、typedefもusingもテンプレートも結局、メンバ変数にしたいクラスの記述と同じよう記述をすれば大丈夫です。

templateクラスの前方宣言ClassAのメンバ変数としてClassFを持つ場合)
template<typename T>
class classF;
class classA
{
public:
	classA();
	~classA();
private:
	classF<int> *objF;
};

ごちゃごちゃしたクラスの前方宣言

いろんな要素が入っていてごちゃごちゃしているクラスも、ちゃんと構造を理解して同じように書いてあげれば大丈夫です。

名前空間があり、templateクラスをtypedefしてさらにusingをした場合の前方宣言ClassAのメンバ変数としてClassGGGを持つ場合)
namespace NS_G{
	template<typename T>
	class classG;
	typedef classG<int> classGG;
	using classGGG = classGG;
}
class classA
{
public:
	classA();
	~classA();
private:
	NS_G::classGGG *objG;
};

注意:インナークラスは前方宣言できない

インナークラスの場合は、前方宣言できません。とっとと諦めて、設計を見直しましょう。

インナークラス前方宣言ClassAのメンバ変数としてClassHinnerを持たせたい、けどビルドエラーの場合)
class classH;
class classH::classHinner;  // NG! 認識できない型(classH)が利用されています
class classA
{
public:
	classA();
	~classA();
private:
	classH::classHinner *objH; // NG!
};

上記ソース全ソースはGithubに上げています(いらないと思いますけど・・・)。

メンバにクラスポインタをもたせると、メモリ管理がめんどくさい・・・いやいや、スマートポインタ使いましょう。
以上、他にもこんな前方宣言があるよって方はご教示ください。

103
88
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
103
88

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?