その秘密は、1 つの定義規則です。インラインが非表示の場合、画像ごとにインラインの複数の (プライベート) コピーが作成される可能性があります。
理想的には、1 つの定義ルールを使用して機能できるようにすべてを構成して使用し、最適化としてプライベート externs を有効にすることができます (これはあらゆる点で、特にバイナリ サイズが適切であるとは限りません)。このアプローチは、標準のモデルに従っているため、好まれます。
ODR を簡単に復習するには:
// somewhere.hpp
namespace MON {
inline int cas(const int*,const int*,int*) {
return dah_dum();
}}
// elsewhere.hpp
namespace MON {
inline int cas(const int*,const int*,int*) {
return dum_dah();
}}
int MON::cas(const int*,const int*,int*)
全体的または部分的にインライン化されていないが、への関数呼び出しは、どのint MON::cas(const int*,const int*,int*)
定義が TU に表示されたかに関係なく、いずれかの定義を使用する結果になる可能性があります。厳密に 1 つの定義がリンカーによって保持され、すべての定義がすべて等しいと見なされます。参照されて表示されるすべての定義が各翻訳のコピーを生成すると、バイナリサイズが爆発するため、これは重要です。
ODR のルールを使用するときに「機能する」場合は、オブジェクト ファイルに特定のシンボルの複数の定義があり、コンパイラの設定により異なる定義を参照することになる可能性があります。静的または匿名名前空間ではないインラインを宣言した場合、その定義はすべてのソース ファイルで同じにする必要があります。
これを C TU と混合している場合は、問題をさらに複雑にするだけのリンケージのルールが異なります。