2011-07-22 7 views
5

可能性の重複:
Proper way to #include when there is a circular dependency?C++での相互インクルード..どのように動作しますか?

私はC++にはかなり新しいですし、タイトルに尋ねた質問があります。より正確に言えば:A.hにB.hが含まれていて、B.hにA.hが含まれている場合、「インクルード#ファイル」C:... \ A.hが「自身を含む」ため、エラーメッセージが表示されます。ファイル:B.h

私はこれを回避する方法を見つけることができませんでした。私の一般的なセットアップでは、これらのクラス間の関係がかなり必要です。 この作品を作成する可能性はありますか?

+0

良い質問です。プリプロセッサは行単位で作業するので、 '#ifdef'、' #define'、 '#endif'がどのように動作するかを調べることができます:-) – Stan

答えて

6

シンプル:A.hにB.h.およびその逆。

一般に、ヘッダーファイルには、可能な限り小さなものを含める必要があります。前方宣言を使用すると、多くのインクルードを回避できます。ヘッダーに何かを絶対含まなければならない唯一の時間は、そのヘッダーで非参照として使用されるオブジェクトがある場合です。

これは避けてください。 Pimplを使用して、クラスメンバーをヘッダーに入れないようにします。また、テンプレートコードでないか、インラインサポートが必要な場合は、実際のコードをヘッダーに記述しないでください。

A.hとB.hに必要なものを定義するC.hを作成する必要があります。

+1

TIL:前方のdelcaration =) – ArniBoy

+0

Thanks @Nicol、それは良い点です。一般的に(二重包含のこの特定のケースではない)、あなたはなぜ前方宣言を通常の包含にするのかを説明してください。 – Enzo

7

ヘッダーファイルにガードを含めます。 http://en.wikipedia.org/wiki/Include_guard

#ifndef MYHEADER_H 
#define MYHEADER_H 

//add decls here 

#endif 

あなたのヘッダファイルはコンパイラがこれらを無視回以上含まれている場合は、この方法で。

また、B.hにA.hが含まれている場合は、B.hのインクルードに頼るのではなく、A.hとB.hをアプリケーションに含める方がよいでしょう。

また、ヘッダーファイルにのみ宣言を挿入します。

ヘッダーファイルのすべてのコストをかけて定義しないでください。

0

ヘッダーガードを追加してみてください、

#ifndef _A_H_ 
#define _A_H_ 
... 
.. 
. 
#endif /* #ifndef _A_H_ */ 

あなたは二回ヘッダファイルをインクルードすることはありません、再定義で結果..ヘッダファイルは、それが前処理部の間に含まれますファイルに追加され

0

コンパイルの。 B.hをA.hに含めます。そして、B.hにA.hを含む。それは無限に再帰的なものであり、ファイルは複数回含まれます。 A.hでB.h含める

はA.h < にのぼる - B.hでB.h A.h含め はBhの< にのぼる -

A.h無限再帰ループのだから、その王。

1

あなたはこれらの相互依存関係は何も言わなかったので、これらは単なる推測です。これらのすべてにおいて、A.hはclass Aを定義し、B.hはclass Bを定義すると仮定する。

ケース1:相互依存関係は、ポインタまたは参照によるものです。
たとえば、class Aには、データタイプがB*であり、その逆もあります。この場合、どちらのヘッダも#includeには必要ありません。代わりに前方宣言を使用してください。

ケース2:相互依存はオブジェクトを介して行われます。
たとえば、class Aには、Bのデータメンバーが含まれ、その逆もあります。この場合、あなたはホースを締めています。

ケース3:混在している依存関係。
たとえば、class Aには、タイプBのデータメンバーが含まれますが、class Bには、データタイプがA*です。今すぐA.hは#include B.hになる必要がありますが、B.hは単にclass Aという前方宣言が必要です。

ヘッダーが複数回含まれないようにするには、一度のインクルードガードを使用する必要があります。

ヘッダファイル:「ああ」#ifndef A_H #define A_H #endif

#ifndef A_H 
#define A_H 
Class B; 

Class A { 
public: 
    B name_of_B_; 
} 

#endif 

あなたは、各ヘッダが一度だけ含まれていることを確認し、各ヘッダには、クラスを持っていると仮定すると

1

することは、あなたは次のように行うことができます。これは、この特別な二重インクルードの場合だけでなく、生成したすべてのヘッダーファイルでこれを使用する必要があります。 Class B;では、 "B"という名前のクラスが定義されていると宣言します。

Class B { 
public: 
    A name_of_A_; 
} 

#endif 

「B」と同じ物語です。このようにして、無限ループの包含を避けます。

+1

各ヘッダーファイルの末尾にあるインクルードは完全に無意味です。クラスAのような前方宣言; Class AとClass Bのどちらが解決されるかは問題ではありません。この時点では、コンパイラにフォワード宣言を使用してコンパイルの終わりに両方とも存在します。したがって、ヘッダファイルの末尾にあるインクルードは、目的を果たさないため削除することができます。よろしく;) – ForceMagic

+0

右!それを指摘してくれてありがとう。 – Enzo

関連する問題