web-dev-qa-db-ja.com

同じ名前と同じメンバー関数が異なる翻訳単位で2つのクラスを持つことができますか?

2つの翻訳単位があるとします。

//A.cpp
class X
{
};

//B.cpp
class X
{
   int i;
};
 _

上記のプログラムはよく形成されていますか?

そうでなければ、それ以上の質問はありません。答えがYESの場合、プログラムは整形式(メインの欠如を無視して)、次に2番目の質問です。それらの中に同じ名前の関数がある場合はどうなりますか?

//A.cpp
class X
{
    void f(){}
};

//B.cpp
class X
{
    int i;
    void f(){}
};
 _

両方のオブジェクトファイルで&x :: fが表示されるため、これはリンカにとって問題になりますか?そのような状況では匿名の名前空間は必須ですか?

14
Armen Tsirunyan

短縮版

まあ、No ... C++ベース名前空間内のすべての名前が一意であるという仮定。あなたがその仮定を破るならば、あなたはそれがうまくいくのを保証することができます。

たとえば、2つの翻訳単位で同じ名前のメソッドがある場合(*.oファイル)。リンカは、与えられた呼び出しに使用するものを知っていて、それがエラーを返すだけです。

長いバージョン

...しかし実際ははい!

同じ名前のクラス/メソッドで逃げることができる場合は、実際にはかなりのいくつかの状況があります。

あなたのプログラムでこれらのトリックを実際に使用しないでください。結果として得られるプログラムを最適化すると思うならば、コンパイラはかなり何もすることができますので、次のように妨げられることのどれかが壊れるかもしれません。

クラスは最も簡単です。非静的メンバーだけでいくつかのクラスを取り上げてください。そのようなことは、コンパイルされたプログラムにトレースを残さない。クラス/構造体は、プログラマがデータを整理するためのツールだけであり、メモリプールやオフセットに対処する必要がない。そのため、基本的に、異なるコンパイル単位で同じ名前の2つのクラスがある場合は、それが機能するはずです。コンパイラがそれらを完了した後、特定のフィールドにアクセスするためにポインタをメモリ内に移動するための数の命令だけで構成されます。リンカを混乱させるだろうここでは何もありません。

コンパイラは*.oファイルにシンボルを作成することがよくあるため、関数と変数(静的クラス変数を含む)はより難しいです。そのような関数/変数が使用されていない場合は、ラッキーリンカーがそれらを無視することができますが、それをカウントしないであろう。ただし、シンボルの作成を省略する方法はあります。静的なグローバル要素または匿名ネームスペースの中の1つは、その翻訳単位の外側には見えません。リンカはそれらに不満を申し立ててはいけません。また、インライン関数は別々のエンティティとして存在しないため、クラス内で定義されている関数はデフォルトでインライン化されているため、ここでは特に関連性があります。シンボルがない場合、リンカは競合を見ません。すべてがコンパイルされるべきです。

テンプレートはまた、それらを使用する各コンパイルユニットの需要に応じてコンパイルされているため、いくつかの汚れたトリックを使用していますが、最終プログラムの単一のコピーとして終了します。これが複数異なると同じであるとは思わないので、トピックを削除しましょう。

結論として、クラスに静的メンバーがない場合、それらは自分の体外の機能を定義していない場合は、同じファイルにそれらを含まない限り、同じ名前の2つのクラスを持つことが可能です。しかしこれは非常に壊れやすいです。現在機能していても、コンパイラの新しいバージョンでは、そのようなプログラムが破壊されるような修正/最適化/変更がある可能性があります。もっと大きなプロジェクトではかなり織り込む傾向があるという事実を一人にしてください。そんな時点で同じ場所に両方のファイルを含める必要があることがわかった可能性があります。

1
NO_NAME