1. ホーム
  2. C++

エラー: 'xxx' は事前宣言と C++ ヘッダーファイルが互いに含まれているため、型名になりません。

2022-02-08 10:26:50
<パス

ソースファイル内でクラスへのポインタを宣言または定義するには、そのクラスを使用する前に宣言または定義する必要があるため、以下のコードではエラーが報告されるでしょう。

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 が宣言または定義されていないためです。
また、ヘッダー同士が含まれる場合にも "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" なぜでしょうか?それでは、"gcc -E -o a.i a.h" というコマンドで前処理をした後に a.h がどのように展開されるかを見てみましょう。

# 1 "a.h"
# 1 "
Ignoring the line starting with "#", we see that it is now almost identical to the opening source file, except that the class order has been swapped, so the cause of the error is the same as the opening source file. 

The solution is also very simple, replace "#include "b.h"" in a.h with the predeclaration "class B;" in class B, and make a similar change in b.h. Make a similar change in b.h. In this case, it will not cause problems. Of course, there is a prerequisite for this: the only members in class A are pointers to class B, not variables of class B, and no members or functions of class B can be accessed in the class A header file. In either case, class A needs to know the size or other details of class B. The predecessor declaration cannot provide these details, and a problem like "error: field 'b' has incomplete type 'B '".
Ignoring the line starting with "#", we see that it is now almost identical to the opening source file, except that the class order has been swapped, so the cause of the error is the same as the opening source file.
The solution is also very simple, replace "#include "b.h"" in a.h with the predeclaration "class B;" in class B, and make a similar change in b.h. Make a similar change in b.h. In this case, it will not cause problems. Of course, there is a prerequisite for this: the only members in class A are pointers to class B, not variables of class B, and no members or functions of class B can be accessed in the class A header file. In either case, class A needs to know the size or other details of class B. The predecessor declaration cannot provide these details, and a problem like "error: field 'b' has incomplete type 'B '".