33

クラス B があり、クラス A からメンバーを呼び出したいと考えています。

1.

//A.h    
class B; 
class A 
{ 
private:
    B* m_p; 
}; 

//a.cpp
#include "B.h"

2.

// A.h
#include "B.h"

class A 
{ 
private: 
    B * impl_; 
}; 

あまり依存していない小さなプロジェクトが関係する場合、どちらの方法が良いですか、この2つは似ていますか?

4

6 に答える 6

38

それを行う最初の方法はa.h、 の存在class B知られているが、その定義は知られていないことを意味します。Bこれにより、 insideでできることが制限されa.hます。たとえば、 型の変数は使用できますが、型の変数は使用できませB *B(型の変数を宣言する場合B、コンパイラは の完全な定義を認識できる必要があるためですB)。また、タイプ の変数がある場合B *、ポインターを逆参照することはできません (そのためにも、 の定義Bがわかっている必要があるため)。

したがって、これらの問題のない 2 番目の選択肢が優先され、ほとんどの人がほとんどの場合これを使用します。

最初の方法が役立つ可能性があるのは、特殊なケースのみです。例えば:

  • .hファイルが互いにインクルードしている場合(ただし、インクルードガードに関しても、さらに多くの問題が発生する可能性があります。これは一般的に困難であり、回避する必要があります);
  • Ifb.hは非常に大きく複雑なため、コンパイル プロセスが遅くなるため、できるだけ含めないようにします。
于 2013-04-05T07:24:02.813 に答える
20

最初のメソッドは前方宣言です。2番目には実際にクラスBが含まれています。

どちらか一方をいつ使用するのですか?

次の場合に最初のものを使用します。

  • Aの定義では、B へのポインタしかありません。つまり、B のメンバーではありません。
  • A の定義から B の関数を呼び出すことはありません(つまり、B のメンバー関数へのすべての呼び出しは、A のメンバー関数を実際に実装する .cpp ファイルで行われます)。
  • クラス B のインターフェイスまたはサイズは頻繁に変更されると予想されますが、A のインターフェイスは変更されません。このように、B が変更された場合、a.cpp の内容のみが再コンパイルされますが、ah (および ah を含む他のファイル) は変更する必要がありません。 .

次の場合に 2 番目のものを使用します。

  • B のサイズを知る必要があります。コンパイラは、クラス定義とそのすべてのメンバーのサイズを使用して、クラスのサイズを計算します。たとえば、クラス A に型 B のメンバーがある場合、A のサイズを計算するには、コンパイラは B のサイズを知る必要があります。B のサイズを知るには、bh を含める必要があります
    • クラス B の関数を呼び出す必要があります。実際に存在する関数を呼び出しているかどうかを知るために、コンパイラはクラス B のインターフェイスを認識する必要があります。つまり、bh を含める必要があります。
于 2013-04-05T07:22:34.200 に答える
0

クラス A のヘッダーでクラスを宣言するだけです。

class B;
于 2013-04-05T07:13:05.980 に答える
0

2番目の方が良いです。クラスはB、ファイルを使用して含めるモジュールになり.hます。B将来サブクラス化し、更新Aして use を使用する場合を考えてみましょうC#include2 番目のケースでは、ヘッダーとの構成のみを置き換えますA。最初のケースでは、前方宣言を変更する必要があります。また、2 番目のケースでは、シンボル以上のものを定義しますB

コメントの#include "B.h"ように、ヘッダー ファイルが残りのコードと同じディレクトリにある場合は、使用する必要があります。

于 2013-04-05T07:13:40.760 に答える
0

あなたがやっていることは前方宣言と呼ばれます。それが必要な理由は、クラス B を使用するクラス A と、クラス A を使用する ALSO クラス B のようなものがある場合です。

リレーションが 1 つしかない場合は、確実に 2 番目の選択肢を使用できます。二重使用が必要な場合は、少なくとも 1 つのクラス宣言で前方宣言を使用する必要があります。

于 2013-04-05T07:14:13.457 に答える