web-dev-qa-db-ja.com

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

Reduce the number of #include files in header files. It will reduce build times. Instead, put include files in source code files and use forward declarations in header files.

これをここで読みました。 http://www.yolinux.com/TUTORIALS/LinuxTutorialC++CodingStyle.html

したがって、ヘッダーファイル内のクラス(クラスA)が一部のクラス(クラスB)の実際の定義を使用する必要がないかどうかを示します。現時点では、特定の(クラスB)ヘッダーファイルをインクルードする代わりに、フォワード宣言を使用できます。

質問:ヘッダー内のクラス(クラスA)が特定のクラス(クラスB)の実際の定義を使用しない場合、前方宣言はコンパイル時間をどのように短縮するのに役立ちますか?

18

コンパイラーは、クラスAがクラスBを使用するかどうかを考慮しません。クラスAがコンパイルされ、クラスBの事前宣言(前方宣言など)がない場合にのみパニックになり、エラーとしてマークします。

ここで重要なのは、猫がキーボードの上を歩き、クラスとして解釈される場合と解釈されない場合があるランダムな文字を作成した後で、コンパイラーがプログラムをコンパイルしようとしなかったことを知っていることです。

インクルードが見つかると、その中に含まれている情報を使用できるようにするために、ファイルを開いて解析する必要があります(実際にそうする必要があるかどうかに関係なく)。そのファイルに他のファイルが含まれている場合は、それらも開いて解析する必要があります。これを回避できる場合は、代わりに前方宣言を使用することをお勧めします。

編集プリコンパイル済みヘッダーであるこのルールの例外。この場合、すべてのヘッダーがコンパイルされ、将来のコンパイルのために保存されます。ヘッダーが変更されない場合、コンパイラーは以前のコンパイルのプリコンパイル済みヘッダーをスマートに使用できるため、コンパイル時間を短縮できますが、ヘッダーを頻繁に変更する必要がない場合にのみ機能します。

12
Neil

なぜなら、A.hppは#include B.hppを必要としないからです。

a.hppは

class B;//or however forward decl works for classes

class A
{
    B* bInstance_;
//...
}

したがって、A.hppが含まれている場合、B.hppは暗黙的に含まれず、A.hppのみに依存するすべてのファイルは、b.hppが変更されるたびに再コンパイルする必要はありません。

4
ratchet freak

C/C++プリプロセッサーは、別個の純粋なテキストによる処理ステップであることを忘れないでください。 #includeディレクティブはインクルードされたヘッダーのコンテンツを取り込み、コンパイラーはそれを解析する必要があります。さらに、各.cppのコンパイルは完全に分離されているため、B.hのコンパイル時にコンパイラがB.cppを解析しただけでは、A.cppのコンパイル時に再度必要になったときに、ほとんど役に立ちません。そして再びC.cppをコンパイルするとき。そして、D.cpp。等々。そして、含まれているファイルが変更された場合、それらの各ファイルを再コンパイルする必要があります。

したがって、クラスAはクラスBを使用し、クラスCおよびDはクラスAを使用しますが、Bを操作する必要はありません。 Aの前方宣言だけでクラスBを宣言できる場合、B.hは2回コンパイルされます:B.cppA.cppをコンパイルするとき(Bのメソッド内でAがまだ必要なため)。

ただし、A.hB.hが含まれている場合は、コンパイルされますfour回—B.cppA.cppC.cppおよびD.cppをコンパイルするとき、後者の2つは間接的にB.hも含むようになりました。

また、ヘッダーが複数含まれている場合でも、プリプロセッサはそれを読み取る必要がありますeach時間。ガード#ifdefsがあるため、コンテンツの処理をスキップしますが、それでも読み取りとガードの終了を検索する必要があります。つまり、内部のすべてのプリプロセッサディレクティブを解析する必要があります。

(他の回答で述べたように、プリコンパイル済みヘッダーはこれを回避するための試みですが、それらは独自のワームの缶です;基本的にそれらをシステムヘッダーに合理的に使用でき、それらの多くを使用していない場合のみプロジェクトのヘッダー)

3
Jan Hudec

前方宣言は、それ自体がさらに多くのヘッダーファイルを含む可能性があるヘッダーファイル全体よりも、解析がはるかに高速です。

また、クラスBのヘッダーファイルで何かを変更した場合、そのヘッダーを含むすべてを再コンパイルする必要があります。前方宣言を使用すると、それはAの実装が存在するソースファイルだけになる可能性があります。ただし、Aのヘッダーに実際にBのヘッダーが含まれている場合、a.hppは、Bを何も使用していなくても、再コンパイルされます。

2