2010-11-28 8 views
2

私はC++標準のODRに関する関連条項を読み直しましたが、この質問はまだ私には開いています。標準では、インライン関数の定義は、それが使用されているすべての翻訳単位に現れなければならず、定義はほぼページに記述されている意味で同一でなければならない。トークンの順序は同じでなければならないと言います。ローカル識別子の名前が含まれていますか?1つの定義ルール:対応するエンティティが異なる名前を持つことはできますか?

つまり、次のプログラムはODRに違反していますか?(私はVisual Studio 2008でそれを自分自身でテストしようとしましたが、0のエラーと0の警告がありましたが、私はこの例を2つの全く異なる定義に変更しても0のエラーと0の警告MSVCの言い訳では、ODR違反のために正式に診断は必要ないことに注意してください)。

//main.cpp 
inline int f(int); 
int main(){ 
    f(3); 
} 
int f(int x){ 
    int z = x; 
    return z*z; 
} 

//other.cpp 
inline int f(int xx){ 
    int zz = xx; 
    return zz*zz; 
} 
+1

@fred:Cにはインライン関数とODRもありますか? –

+0

それはありますか?気軽にロールバックしてください。インライン関数はC++のみでした。 – fredoverflow

+0

是非、私は盲目的に答えを信じることはできません。あなたが何らかの答えに同意するなら、それをupvoteしてください:) –

答えて

3

識別子は一種のトークンです。各識別子は別々のトークンです。したがって、ODRを尊重するためには同じ識別子が必要です。これは、これを検出するコンパイラ(エクスポートされたテンプレートを使用してコモのサンプルを作成する準備ができている人か、ODRの違反を検出できる人)に違いがあります。

ここではCとC++の違いがあります。 Cには一般的にODRがなく、C99のインライン関数の規則(C90ではインライン関数はありません)はC++のものと大きく異なります。 C99では、コードが正しいです。実際には完全に異なる定義を提供することができます。その結果、Cでは(ただしC++ではなく)同じ定義を使用し、その定義に静的メンバーがある場合、関数を使用するTUと同じ数の静的変数があります。

+1

+1ですが、最後の文を明確にすることができます(現在、CまたはC++のいずれかを表すように思えます)。 –

+1

Cインライン関数の静的オブジェクトに関しては、標準で次のように書かれています:* "外部リンケージを持つ関数のインライン定義は、静的記憶期間を持つ変更可能オブジェクトの定義を含んではいけません。内部リンケージを持つ識別子。 "* – caf

5

はい、ODRに違反します。これは、異なるトークンシーケンスを使用して、私はここで理解するのが難しいのか分からない。

従来のコンパイル手法では、翻訳単位でODRを確認することは困難(不可能)です。標準では「診断不要」と表示されているため、定義されていない動作が発生します。

例を使用すると、さらに微妙なエラーが発生することがあります。無関係な翻訳単位で定義されているが同じ名前の2つの異なるクラス。仮想テーブルがある場合、エラーメッセージなしで衝突する可能性があります(それは私の友人に起こりました)。したがって常には、ローカル関数とクラスに対して匿名の名前空間を使用します。

2

識別子はトークンなので、トークン規則の同じシーケンスによって、プログラムはODRに違反します。

関連する問題