3

次の 2 つの構造体を検討してください。

struct A
{
    // A bunch of standard layout data
};

struct B:public A
{
    // Other data
};

そして、オブジェクト

B foo;

sizeof(A) がコンパイラ間で異ならない場合、パッキングは同じであり、B は仮想メソッドを追加しません。 Windows x86 の gcc または msvc を使用してコンパイルする場合、foo は &foo に相対する同じアドレスに A メンバーを持ちます。 x86-64 プラットフォーム?

編集: 継承を実装する最善の方法は、B の前に A を配置することであることに気付きました。少なくとも GCC は、A のコンテンツの後に B のコンテンツを置きます。

4

2 に答える 2

2

x86_64 アーキテクチャが問題です。GCC と MSVC は異なるメモリ モデルを選択しました。GCC は LP64、MSVC は LLP64 です。つまり、long型は GCC では 64 ビット、MSVC では 32 ビットです。

質問では「同じアドレス」はかなりあいまいですが、A と B が同じコンパイラによってコンパイルされていない場合、問題が発生することは明らかです。その場合、異なるパッキングも問題になる可能性があります。同じあいまいさから補間すると、B に仮想メンバーが含まれていて、A に含まれていない場合、A と B のレイアウトには互換性がありません。B には v-table ポインターが挿入されます。

于 2013-01-03T07:48:11.260 に答える
1

ハンスはすべてを正しく説明しました。一般的な答えは NO です。これは、どのクラス/コンパイラなどでもそのままでは機能しません。

それにもかかわらず。C++には#pragma pack、クラス内のアライメントレコードなどの機能があります。これらはすべて、必要なまたは事前定義されたメモリレイアウトを生成するためのものです。それらを慎重に使用する場合(おそらくいくつかの場合#ifdefsも)、必要な互換性が得られます。これは多くのプロジェクトで使用され、機能しました。

ただし、使用するすべてのコンパイラのレイアウトを注意深く確認する必要があります。

于 2013-01-03T10:31:33.003 に答える