基本は次のとおりです。
任意の型について、型、、、、などのA
変数を宣言する場合、コンパイラは変数宣言の場所での完全な定義を知る必要はありません。知っておく必要があるのは型だけです。それだ。したがって、前方宣言で十分です。A&
A*
A**
A***
A
A
class A; //forward declaration
class B
{
A * pA; //okay - compiler knows A is a type
A & refA;/ okay - compiler knows A is a type
};
コンパイラはとに依存するものをまだ計算できるため、完全な定義は必要ありませ ん 。は、そのプラットフォームでのポインターのサイズにすぎないことに注意してください(通常、32 ビット システムではバイト、64 ビット システムではバイトです)。sizeof(B)
sizeof(A*)
sizeof(A&)
sizeof(A)
sizeof(A*)
4
8
任意の type について、 type 、などA
の変数を宣言する場合、コンパイラは変数宣言の場所で type の完全な定義を知る必要があります。この場合、前方宣言は十分ではありません。A
A[N]
A[M]N]
A
class A; //forward declaration
class B
{
A a; //error - the compiler only knows A is a type
//it doesn't know its size!
};
しかし、これは正しいです:
#include "A.h" //which defines A
class B
{
A a; //okay
};
コンパイラが を計算するには、完全な定義が 必要ですsizeof(A)
が、コンパイラが の定義を認識していない場合、これは不可能ですA
。
クラスの定義とは、「クラス メンバー、その型、およびクラスに仮想関数があるかどうかの完全な仕様」を意味することに注意してください。コンパイラがこれらを認識している場合、クラスのサイズを計算できます。
これらの基本を知っていれば、ヘッダーを他のヘッダーに含めるか、前方宣言のみで十分かを判断できます。前方宣言で十分な場合は、それを選択する必要があります。必要な場合にのみヘッダーを含めます。
A
ただし、ヘッダーで の前方宣言を提供する場合は、 の実装ファイルにB.h
ヘッダー ファイルを含める必要があります。これは、 の実装ファイルでは、コンパイラが の完全な定義を必要とするメンバーにアクセスする必要があるためです。 . 繰り返しますが、 のメンバーにアクセスする必要がある場合にのみ含めてください。:-)A.h
B
B.cpp
B
A
A
A
申し訳ありませんが、回答の最後の段落が表示されませんでした。私を混乱させているのは、なぜ前方宣言も必要なのかということです。ヘッダー ファイル Ah をインクルードしないだけで、クラス A の完全な定義が提供されますか?? –</p>
ヘッダーファイルに何があるかわかりません。また、ヘッダー ファイルをインクルードしているにもかかわらず、前方宣言も提供する必要がある場合は、ヘッダーが正しく実装されていないことを意味します。循環依存関係があると思われます:
2 つのヘッダー ファイルが互いにインクルードされないようにしてください。たとえば、 をA.h
含む場合、直接または間接的に を含めてB.h
はなりB.h
ません。A.h
このような循環依存を解消するには、前方宣言とポインタ宣言を使用します。ロジックはかなり単純明快です。A.h
inを含めることができない場合は、inB.h
を宣言できないことを意味します(このため、ヘッダーも含める必要があるため)。したがって、 を宣言することはできませんが、 を宣言することはできます。これには、 の前方宣言で十分です。そうすれば、循環依存関係を壊すことができます。A a
B.h
A.h
A a
A *pA
A
それが役立つことを願っています。