通常、ヘッダーでインライン化された関数を(宣言するだけでなく) 定義します。
また、インライン化されていない関数 (本体が十分に大きい関数など) を宣言し、特定のコンパイル単位で定義 (つまり、実装) します。
次に、リンカはリンク時に適切な関数名 (通常はマングルされた名前) を解決します。そして、複数定義された関数を持ちたくありません。
関数定義を 1 つのコンパイル ユニットのみで提供すると、全体のビルド時間が少し速くなります。
リンク時の最適化(たとえば、コンパイル中とリンク中の両方のオプション-flto
) を使用g++
すると、事態はさらに複雑になります。
巨大なソフトウェア (一部の実行可能ファイルはほぼ 1 ギガバイトのバイナリーであり、それらをリンクするだけで数分かかります) は、1 人のプログラマーには想像もつかないような制約をもたらすことに注意してください。大規模なフリー ソフトウェア (Libreoffice、Firefox、Qt5 など) をソース コードからコンパイルして、問題を推測してみてください。
ところで、原則として、あるプログラムのすべてのコードを 1 つのソース ファイルに入れることができますが、正当かつ明白な理由により、人々はそうしません。