2017-07-31 22 views
1

ODRを理解しようとしています。 私はこのような一つのファイルpr1.cppを作成:1定義ルール - 編集

struct S{ 
    int a; 
}; 

この

struct S { 
    char a; 
}; 

と、このようなメインファイルのような第二のファイルpr2.cpp:

#include <iostream> 

int main() { 
    return 0; 
} 

私はコンパイルしていますコマンドを使用して端末を使用する:

g++ -Wall -Wextra pr1.cpp pr2.cpp main.cpp -o mypr 

コンパイラは何のエラーも見つけませんが、 "S"型の宣言が2つあります...実際に起こっていることを理解していません。 "リンケージ"フェーズの後にエラーが発生すると思いますODR違反.. は、私はエラーが唯一の追加main.cppにファイルを編集することができます:

#include "pr1.cpp" 
#include "pr2.cpp" 

を誰もが何が起こっているのか私にexmplainすることはできますか?

+1

どちらのオブジェクトも決して作成しないので、コードが破棄されたと見なします。 – xyious

+1

[動作は未定義です。](http://eel.is/c++draft/basic.def.odr#6.sentence-4) – cpplearner

+2

POD構造は実際にはコンパイル時のもので、使用されていないものは、オブジェクトや実行可能ファイルにはトレースがありません。同じ名前の2つの異なる構造体を定義しているため(実際にはスペースを変更するだけで、メンバが同じであってもそれらを異ならせることができます)、*技術的には未定義の動作*です。 –

答えて

-1

両方の定義を同じファイルに含める場合を除き、問題はありません。これは、コンパイラが通常は.cppファイルである単一の翻訳単位で動作するためです。プリプロセッサは基本的にすべてのインクルードファイルの内容をコピーして貼り付けるので、このファイルの#includeはすべて翻訳単位の一部です。

コンパイラが各翻訳単位のファイル(.obj)を作成してオブジェクトファイル(通常は.obj)を作成し、リンカはすべてのオブジェクトファイルとライブラリをプロジェクトにリンクして単一の実行ファイル(または.dllなど)を作成します依存している。あなたのケースでは、コンパイラは異なる構造体の各構造体に遭遇したので、問題は見られません。両方のファイルをインクルードすると、2つの定義が同じ翻訳単位になり、コンパイル時にエラーがスローされます。Sがこの翻訳単位で使用されていると、あいまいさを解決できないためですプログラムが不正に形成される)。

補足として、他の.cppファイルに.cppファイルを含めないでください。ヘッダーとソースファイルでコードを整理する方法については多くのことがわかります。質問に直接答えないので、私はそれを展開しません。

編集:リンカーエラーが表示されなかった理由を忘れました。これは未定義の振る舞いであることを指摘しているコメントがあります。これは、リンカーがおそらく実際には必要ないと不平を言っても意味があることを意味します。あなたの場合、それぞれの構造体とmain.objに対して1つの.objファイルがあります。これらのどれも他のものを参照していないので、リンカは解決する必要のある参照を見つけられず、おそらくあいまいなシンボルをチェックすることはありません。

私はあなたがstruct S;を宣言し、S*またはS&(実際Sは、同じ翻訳単位内の定義を必要とする)を使用しようとした場合、ほとんどのリンカーはエラーをスローしますと仮定します。これは、リンカがそのシンボルを解決する必要があり、2つの一致する定義が見つかるためです。しかし、これは未定義であるため、標準準拠のリンカはただ一つを選んで、あなたのプログラムを無意味なものに黙ってリンクすることができます。これは、定義が一貫している必要があるため、ある.cppから他の.cppに渡される構造体にとって特に危険です。同じ名前の構造体/クラスがライブラリの境界を通過する場合にも問題になる可能性があります。これらの理由から、名前の重複は避けてください。

+1

あなたはリンカが私が思う2つの定義について不平を言っていない理由に答えるつもりはありません。 – Rakete1111

+0

私は行こうとしていましたが、私はその部分を取り除くことに決めました。なぜなら、OPは特に編集に関するものだと感じたからです。 – patatahooligan

+0

私は何とかOPのリンクフェーズへの参照を見逃してしまった – patatahooligan

関連する問題