1. ホーム
  2. c++

[解決済み】C++でクラス名が型名にならない

2022-02-09 05:19:13

質問

C++でプログラミングを始めたばかりですが、2つのクラスを作成して、一方が他方を含むようにしようとしました。

ファイル A.h :

#ifndef _A_h
#define _A_h

class A{
    public:
        A(int id);
    private:
        int _id;
        B _b; // HERE I GET A COMPILATION ERROR: B does not name a type
};

#endif

ファイル A.cpp :

#include "A.h"
#include "B.h"
#include <cstdio>

A::A(int id): _id(id), _b(){
    printf("hello\n the id is: %d\n", _id);
}

ファイル B.h :

#ifndef _B_h
#define _B_h

class B{
    public:
        B();
};
#endif

ファイル B.cpp :

#include "B.h"
#include <cstdio>

B::B(){
    printf("this is hello from B\n");
}

まずBクラスをコンパイルし、次にAクラスをコンパイルするのですが、エラーメッセージが表示されます。

A.h:9: error: 'B' does not name a type

この問題を解決するにはどうしたらいいですか?

どのように解決するのですか?

プリプロセッサは、ファイルの内容を挿入します。 A.hB.h を使用することができます。 include ステートメントが発生します (これは実際には単なるコピー・ペーストです)。コンパイラが A.cpp の宣言が見つかります。 A について知る前に、クラス B . このため、ご覧のようなエラーが発生します。これを解決するには、2つの方法があります。

  1. 以下を含む B.hA.h . 一般的に、ヘッダーファイルは必要なファイルにインクルードするのが良い方法です。他のヘッダを間接的にインクルードしたり、コンパイル単位(cpp-file)で特別な順序でインクルードしたりすると、プロジェクトが大きくなったときに、あなたや他の人を混乱させるだけでしょう。
  2. 型のメンバ変数を使用する場合 B クラス内の A の正確で完全な宣言をコンパイラが知る必要があります。 B のメモリレイアウトを作成する必要があるからです。 A . 一方、ポインタや参照で B なぜなら、コンパイラがポインタや参照用に確保する必要のあるメモリは、クラス定義とは無関係だからです。この場合、次のようになります。

    class B; // forward declaration        
    class A {
    public:
        A(int id);
    private:
        int _id;
        B & _b;
    };
    
    

    これは、ヘッダー間の循環的な依存関係を避けるために非常に便利です。

お役に立てれば幸いです。