【C++】ヘッダークラス内で別のクラスを使用する場合の宣言方法

目次

ヘッダークラス内で、別のクラスを使用したい場合の宣言方法

コードで示したほうがわかりやすいと思うので、以下を参考にしてください。

使わる側のTest1ヘッダー

1
2
3
4
5
6
7
class Test1{
public:
Test1();
private:
int mX;
int mY;
};

使う側のTest2ヘッダー

1
2
3
4
5
6
class Test2{
public:
Test2(Test1 test1);
private:
Test1 *mTest1; // Test1クラスのポインタを保持したい
};

上記のコードでは、正常な動作はされず、Test1が見つかりません。というエラーが出ます。

これは、Test2をIncludeしていないので、定義されていないと判定されてしまうためです。

includeとは何か

ここで、C++のincludeの使用について解説しておきます。

C++のincludeは単純に指定したファイルの中身をincludeしたファイルに展開することです。

なので、includeしていない = 前方宣言されていないということになるのです。

別のクラスをメンバとして保有する方法

ここで、本題に戻ります。最初に提示したTest2でコンパイルエラーを発生させないためには、前方宣言が必要だということでした。結果として保有したいクラスをコンパイラが事前に知っていればいいということになります。

  1. include “クラス名.h”でクラスをインポートする
  2. class Test1;をファイルの先頭に書いておく
  3. メンバ変数宣言時にclass Test1 *mTest1;と記述する

1. include “Test1.h”でクラスをインポートする

この方法は一番単純ですが、使用しないクラスのインポートが発生してしまいます。

1
2
3
4
5
6
7
8
#include "Test1.h"    //  追記

class Test2{
public:
Test2(Test1 test1);
private:
Test1 *mTest1;
};

2. class Test1;をファイルの先頭に書いておく

この方法では、Test1という何もしないクラスを定義して、クラスを認識させます。

注意点としては、Test1はこの時点では何も定義されていないので、本物のTest1の中の関数やメンバ変数は使用できません。

1
2
3
4
5
6
7
8
class Test1;

class Test2{
public:
Test2(Test1 test1);
private:
Test1 *mTest1;
};

3. メンバ変数宣言時にTest2(class Test1 test1);と記述する

この方法は、2がファイルの一番最初に書いているのに対して、毎回 or 最初にTest1を使用するときにclass クラス名と書くことで、前方宣言しているのと同じ効果を持たせることができます。

最初にTest1を使用するときに宣言する

1
2
3
4
5
6
class Test2{
public:
Test2(class Test1 test1); // ここだけに書いておけばOK
private:
Test1 *mTest1;
};

or

全てのTest1を使用するときに宣言する

1
2
3
4
5
6
class Test2{
public:
Test2(class Test1 test1); // class 追記
private:
class Test1 *mTest1; // class 追記
};

まとめ

極力includeは使用しないほうが無駄なコンパイルが発生しなくなるので、個人的には、3の最後のすべてにclass クラス名で使用するのがわかりやすくていいかなと思いました。

参考

【C++】ヘッダークラス内で別のクラスを使用する場合の宣言方法

https://blog.djima.net/2021/09/03/【C-】ヘッダークラス内で別のクラスを使用する場合の宣言方法/

Author

Daiki Iijima

Posted on

2021-09-03

Updated on

2024-04-17

Licensed under