1

ここですでに質問されているほとんどのものとは異なる循環ヘッダーの問題があります。相互に依存しているがメンバーとしては依存していない 2 つのクラスがあるため、コンパイラがクラスのサイズを計算できないという問題に遭遇しないでください。そのため、前方宣言を使用してサイクルを断ち切ることができます。

ただし、クライアントがクラスを使用するためにこれらのヘッダーを両方とも含める必要はありません。ユーザーがこの依存関係を意識する必要がないように、ヘッダーは自己完結型である必要があります。これを行う方法はありますか?

編集:注意が必要なのは、 A と B をヘッダーのみで定義する必要があることです。

ヘッダー A.hpp 内

#ifndef A_HPP
#define A_HPP

#include "B.hpp"

struct A
{
    B foo() { ... }
};

#endif

ヘッダー内 B.hpp

#ifndef B_HPP
#define B_HPP

struct A;

struct B
{
    void bar()
    {
        A a = A();
        ...
    }
};

#endif

main.cpp で

#include "B.hpp"
B().bar(); // error: 'a' uses undefined class 'A'
4

4 に答える 4

3

ヘッダー B.hpp

#ifndef B_HPP
#define B_HPP

struct A;

struct B
{
   void bar();
};

#endif

ソース B.cpp

#include "A.hpp"

void B::bar()
{
   A a;
}

編集。したがって、ヘッダーのみの実装が必要な場合は、AndreyT ソリューションを使用してください。

于 2012-07-19T00:48:35.283 に答える
2

B.hpp#include "A.hpp"の末尾に aを追加するだけです。まだ循環インクルードがありますが、何も害はありません。

于 2012-07-19T01:09:54.097 に答える
2

両方のヘッダーに、もう一方のタイプを完全にする必要があるコードが含まれている場合、通常、自己完結型のヘッダーでは実装できない可能性があります。

特定の例(単純すぎて代表的ではない)では、定義B::barを次のように単純に移動できますA.hpp

inline void B::bar()
{
    A a = A();
    ...
}

しかし、もちろん、B定義済みのメソッドを持つことA.hppはあまりエレガントに見えません。

の「インライン化」B::barが重要な場合、「産業用」ソリューションでは、 の定義をB::bar追加のヘッダー ファイルに配置する必要がありますB_aux.hpp。ヘッダーを含めるときは、すべての「通常の」ヘッダーを含めた後に「aux」ヘッダーを含める必要がありmain.cppます。

#include "A.hpp"
#include "B.hpp"
#include "C.hpp"
...
#include "B_aux.hpp"
...

しかし、これは明らかに「自己完結型」のアプローチではありません。

于 2012-07-19T00:49:36.287 に答える
0

通常、循環インクルードは、2 つのタイプが密接に関連していることを示しており、それはそれらが単一のコンポーネントであることを意味している可能性があります。その場合は、2 つのヘッダーをコンポーネントの 1 つのヘッダーにマージします。両方の型が完全に定義されたら、最初に型宣言を行い、メンバー関数の定義を最後にします。

于 2012-07-19T02:16:17.267 に答える