前置き宣言とC++ヘッダファイルの相互包含によるerror:'xxx'does not name a type問題
ソース・ファイルでクラスのポインタを宣言または定義する場合は、使用前にクラスを宣言または定義する必要があります.そのため、次のコードはエラーを報告します.
エラーが「error:‘B’does not name a type」となったのは、AクラスでB*bを使用する前にBクラスを宣言または定義していないためであり、最初の行に前置き宣言(forward declaration)「class B;」を付けると、このような問題はありません.ヘッダファイルが互いに含まれている場合、「error:『xxx』does not name a type」というエラーの原因は上のコードと同じです.次のコードを見てください.a.h:
b.h:
main.cpp:
コンパイルすると「error:『A』does not name a type」と間違えてしまいますが、なぜそうなるのでしょうか.a.hが前処理を経てどのように展開されるかを見てみましょう.前処理コマンドは「gcc-E-o a.i a.h」です.
「#」で始まる行を無視すると、クラスの順序が交換されただけで、エラーの原因は最初のソースファイルと同じであることがわかります.解決策も簡単で、a.hの「#include“b.h”」をBクラスの前置き宣言「class B;」に置き換え、b.hでも同様の修正を行います.これで問題にならない.もちろん、AクラスのメンバーはBクラスのポインタだけで、Bクラスの変数は持てないという前提があります.Aクラスヘッダファイルでは、Bクラスのメンバーまたはメンバー関数にアクセスできません.いずれの場合もAクラスはBクラスの大きさやその他の詳細を知る必要があり、前置き宣言ではこれらの詳細を提供できず、「error:field‘b’has incomplete type‘B’」のような問題が発生する.
class A
{
public:
B *b;
};
class B
{
public:
A *a;
};
int main()
{
return 0;
}
エラーが「error:‘B’does not name a type」となったのは、AクラスでB*bを使用する前にBクラスを宣言または定義していないためであり、最初の行に前置き宣言(forward declaration)「class B;」を付けると、このような問題はありません.ヘッダファイルが互いに含まれている場合、「error:『xxx』does not name a type」というエラーの原因は上のコードと同じです.次のコードを見てください.a.h:
#ifndef A_H_INCLUDED
#define A_H_INCLUDED
#include "b.h"
class A
{
public:
B *b;
};
#endif // A_H_INCLUDED
b.h:
#ifndef B_H_INCLUDED
#define B_H_INCLUDED
#include "a.h"
class B
{
public:
A *a;
};
#endif // B_H_INCLUDED
main.cpp:
#include "a.h"
#include "b.h"
int main()
{
return 0;
}
コンパイルすると「error:『A』does not name a type」と間違えてしまいますが、なぜそうなるのでしょうか.a.hが前処理を経てどのように展開されるかを見てみましょう.前処理コマンドは「gcc-E-o a.i a.h」です.
# 1 "a.h"
# 1 ""
# 1 ""
# 1 "a.h"
# 1 "b.h" 1
# 1 "a.h" 1
# 5 "b.h" 2
class B
{
public:
A *a;
};
# 5 "a.h" 2
class A
{
public:
B *b;
};
「#」で始まる行を無視すると、クラスの順序が交換されただけで、エラーの原因は最初のソースファイルと同じであることがわかります.解決策も簡単で、a.hの「#include“b.h”」をBクラスの前置き宣言「class B;」に置き換え、b.hでも同様の修正を行います.これで問題にならない.もちろん、AクラスのメンバーはBクラスのポインタだけで、Bクラスの変数は持てないという前提があります.Aクラスヘッダファイルでは、Bクラスのメンバーまたはメンバー関数にアクセスできません.いずれの場合もAクラスはBクラスの大きさやその他の詳細を知る必要があり、前置き宣言ではこれらの詳細を提供できず、「error:field‘b’has incomplete type‘B’」のような問題が発生する.