3


1

フォワード宣言とインクルード

ライブラリを操作するとき、それが自分のものであろうと外部のものであろうと、前方宣言を持つクラスがたくさんあります。 状況に応じて、同じクラスにも含まれています。 特定のクラスを使用する場合、そのクラスが使用する特定のオブジェクトが前方宣言されているのか、#include(d)なのかを知る必要があります。 その理由は、両方のヘッダーを含めるのか、それとも1つだけを含めるのかを知りたいからです。

今では、チェックするのはかなり簡単で、コンパイルするだけです(または、問題のオブジェクトが#include(d)またはforward宣言されるまで、すべてのヘッダーを調べます)。 しかし、大規模なプロジェクトでは、単純なコンパイルに時間がかかり、各インクルードファイルを調べて、問題のクラスがインクルードされているか前方宣言されているかどうかを確認するのは、特に深さが数レベルの場合は面倒です。 問題をさらに説明するには:

_ クラスAはクラスB、クラスFooへのポインタを持つクラスCです。 _

クラスAを含め、Class Fooをすぐに使用できる状態になっているかどうか、または次のことを行う必要があるかどうかを知りたいです。

#include "ClassA.h"
#include "ClassFoo.h"

だから、依存するヘッダーをコンパイルしたり、ヘッダーに入れたりすることなく、この依存関係をすばやく簡単に見つける方法はありますか? (私がこの質問をする理由の1つは、機能がまだ存在しない場合、最終的にVS用のアドインやスタンドアロンプ​​ログラムを作成したいからです)

ありがとうございます。

3 Answer


7


ソースファイルでは、他のヘッダーファイルに含まれるものに依存しないでください。

コードが依存するすべてのタイプを明示的に含める必要があります。 +型を使用しない場合(つまり、単にポインタまたは参照を渡すだけの場合)、その定義は必要ないため、ヘッダーファイルを含めないでください(使用しているメソッドのヘッダーファイルには、少なくとも前方宣言)。

そのため、特定のインスタンスではわかりにくいです。 +ソースファイルがFooのメンバーを明示的に使用している場合、「ClassFoo.h」を含める必要があります。そうでない場合は含めません。 ヘッダーファイルを掘り下げる必要はありません(変更される可能性があります)。 ソースファイルが使用しているものを正確に確認し、それら(およびそれらのみ)のヘッダーファイルを含めてください。

ヘッダーファイル:包含よりも前方宣言を優先します。 このようにして、循環依存関係を制限/解除します。


1


実際、私は*人間が可能な限り多くのヘッダーを含む*を排除することを見つけています*実際に* hella *を助けます。 https://stackoverflow.com/questions/3962708/how-much-do-forward-declarations-affect-compile-time/3962760#3962760 [この回答を参照]。 より多くの #include`ステートメントを削除することにより、ソースファイルの一部を正確に*はるかに*明確にできます(#includes`はブラックボックスです-その1行のテキストによって何がリンクされているかわかりません)。 クラスFooがクラスBarの実装の詳細を必要とする場合、Foo.hは「Bar.h」を*含めるべきではなく、むしろ、前方宣言のみを含むべきです。 Foo.cppにはBar.hを含める必要があります。

Foo.h

class Bar ; // fwd declare wherever possible

class Foo
{
  // I can haz needs Bar
  void do( Bar *bar ) ;
} ;

Foo.cpp

#include "Foo.h"
#include "Bar.h" // I can has needs complete implementation details.

Foo::do( Bar *bar )
{
}

Bar.h

class Bar
{
  // code..
} ;


0


「クラスA」を使用している場合は、基本クラス「C」のプライベートインターフェイス(および場合によっては「A」の追加インターフェイス)のみに注意する必要があります。 クラスが適切に設計されていれば、 F`に直接アクセスする必要はありません。これは、 C`のインターフェースにカプセル化され、公開されないためです。 この場合、 C`のパブリックインターフェイスの一部ではないため、 Foo`へのインクルードはまったく必要ありません。 実際、「Foo」が何らかの形で「C」へのインターフェースの一部である場合、「Ch」には「Foo.h」も含める必要があると主張します。再び尋ねる。