C ++で前方宣言が必要な理由
コンパイラーは、スペルミスや間違った数の引数を関数に渡していないことを確認したいと考えています。そのため、使用される前に、まず 'add'(またはその他の型、クラス、関数)の宣言を確認するように要求しています。
これにより、コンパイラーはコードの妥当性検査をより適切に実行できるようになり、ルーズエンドを整理して、見栄えの良いオブジェクトファイルを生成できるようになります。宣言を転送する必要がなかった場合、コンパイラーは、関数「add」が何であるかについて考えられるすべての推測に関する情報を含む必要があるオブジェクトファイルを生成します。そして、リンカは、「add」関数がaddを使用して生成するオブジェクトと結合している別のオブジェクトファイルに存在する場合に、実際に呼び出すつもりの「add」を試すための非常に巧妙なロジックを含む必要があります。 dllまたはexe。リンカーが誤った追加を取得する可能性があります。int add(int a、float b)を使用したいが、誤って書き込みを忘れたが、リンカが既存のint add(int a、int b)そしてそれは正しいものであると考え、代わりにそれを使用しました。コードはコンパイルされますが、期待どおりに動作しません。
そのため、物事を明確に保ち、推測などを避けるために、コンパイラは、使用する前にすべてを宣言するように要求します。
宣言と定義の違い
余談ですが、宣言と定義の違いを知ることは重要です。宣言は、何かがどのように見えるかを示すのに十分なコードを提供するだけなので、関数の場合、これは戻り値の型、呼び出し規約、メソッド名、引数、およびそれらの型です。ただし、メソッドのコードは必要ありません。定義には、宣言が必要であり、関数のコードも必要です。
前方宣言でビルド時間を大幅に削減する方法
関数の宣言を現在の.cppまたは.hファイルに取り込むには、関数の宣言が既に含まれているヘッダーを#includします。ただし、これによりコンパイルが遅くなる可能性があります。特に、プログラムの.cppではなく.hにヘッダーを#includeする場合、作成している.hを#includeするすべてのものがすべてのヘッダーを#includeすることになるためです。あなたも#includesを書きました。突然、コンパイラには#includeされたページとコードのページが含まれ、1つまたは2つの関数のみを使用したい場合でも、コンパイルする必要があります。これを回避するには、前方宣言を使用して、ファイルの先頭に関数の宣言を入力します。いくつかの関数のみを使用している場合、これにより、常にヘッダーを#includeするよりもコンパイルが速くなります。本当に大きなプロジェクトの場合、
2つの定義の両方が互いに使用する循環参照を解除する
さらに、前方宣言はサイクルを断ち切るのに役立ちます。これは、2つの関数の両方が互いに使用しようとする場所です。これが発生した場合(そしてそれを行うことは完全に有効なことです)、1つのヘッダーファイルを#includeすることができますが、そのヘッダーファイルは、現在作成しているヘッダーファイルを#includeしようとします。 、あなたが書いているものを#includeします。あなたは鶏と卵の状況に行き詰まり、各ヘッダーファイルはもう#includeを再組み込みしようとしています。これを解決するには、ファイルの1つで必要な部分を前方宣言し、そのファイルに#includeを残します。
例えば:
ファイルCar.h
#include "Wheel.h" // Include Wheel's definition so it can be used in Car.
#include <vector>
class Car
{
std::vector<Wheel> wheels;
};
Wheel.hファイル
うーん... WheelにはCarへのポインターがあるため、ここではCarの宣言が必要ですが、Car.hを含めることはできません。コンパイラエラーが発生するためです。Car.hがインクルードされた場合、それはWheel.hをインクルードするWheel.hをインクルードしようとし、これはWheel.hをインクルードし、これは永遠に続くため、コンパイラはエラーを発生させます。解決策は、代わりにCarをフォワード宣言することです:
class Car; // forward declaration
class Wheel
{
Car* car;
};
Wheelクラスにcarのメソッドを呼び出す必要があるメソッドがある場合、それらのメソッドはWheel.cppで定義でき、Wheel.cppはサイクルを引き起こすことなくCar.hを含めることができるようになりました。