プリプロセッサの定義は、現在のコンパイル単位に対してローカルです。
もちろん複雑なケースもありますが、ポイントは次のとおりです。
.cpp (ソース) ファイルを個別のエンティティとして見るようにしてください。本当に奇妙なことをしなければ、気になるものを除いてすべての .cpp ファイルを削除すれば、コンパイル段階では定義は必要なく、ものの名前 (宣言) だけを気にするため、コンパイルできます。
したがって、N 個のソース ファイルを 1 回の実行でコンパイルすると、基本的に次のようになります。
[ *.H + SOURCE1.CPP ] --> SOURCE1.O
[ *.H + SOURCE2.CPP ] --> SOURCE2.O
...
[ *.H + SOURCEN.CPP ] --> SOURCEN.O
ここで、すべての行は個別のコンパイル単位であり、SourceX.CPP と含まれているヘッダーをオブジェクト ファイルにレンダリングします。それで、ここにN個の別のものがあります。
このように、共通ヘッダーを変更しない場合、変更されていないソース ファイルを再コンパイルする必要はありません。もちろん、ソース ファイルを変更した場合は、それを再コンパイルする必要があります。最後に、共通ヘッダーを変更する場合は、それを含むすべてのソース ファイルを再コンパイルする必要があります。ここで、コンパイル フェーズの前に、すべての
#inlude "filename.ext"行 (プリプロセッサ ディレクティブ) が filename.ext ファイルの正確な内容に置き換えられることに注意する必要があります。
次に、リンクは別の問題です。その段階での目標は、その N 個のオブジェクト ファイルから 1 つのファイルを作成することです。(繰り返しますが、これは単純なケースです)
これはリンクしています:
[ SOURCE1.O + SOURCE2.O + ... + SOURCEN.O ] --> EXECUTABLE.FILE
影響を受けるオブジェクト ファイルが、値とアルゴリズム (関数定義) のバッグであると想像してください。たとえば、バッグのどこかに正確に 1 つの
main関数 (定義) が存在する必要があるため、リンカーは、プログラムを実行するときに何をすべきかを確実に認識します。
あなたがそれを手に入れたことを願っています
グローバル関数の定義をヘッダー ファイルに書き込んで、それを 2 つの別々のコンパイル ユニットにインクルードすると、それらをリンクしようとするとどうなるでしょうか。
答え: リンカー エラー - 複数の定義。それらは個別にコンパイルできるためです。