6

これは、これに対するフォローアップの質問です

次の例を検討してください。

#include <iostream>

class A
{
};

class B : public A
{
    public:
    int i;
    virtual void Func() = 0;
};

class C : public B
{
    public:
    char c;
    void Func() {}
};

int main()
{
    C* pC = new C;
    A* pA = (A*)pC;
    std::cout << "pC == " << std::hex << pC << "\n";
    std::cout << "pA == " << std::hex << pA << "\n";
    return 0;
}

Visual Studio 2010 では、出力は (私のマシン上で):

pC == 002DEF90
pA == 002DEF94

(これは、質問の受け入れられた回答によって説明されています)。

g++ を使用すると、出力は次のようになります。

パソコン == 0x96c8008
pA == 0x96c8008

では、問題は、g++ の実装がこのケースをどのように処理するかということです。Cvtableが必要な場合にアドレスを同じにするのは何ですか? (これが実装の詳細であることは知っていますが、そうは言わないでください :) 私は好奇心からこの実装の詳細に興味があります)。

4

1 に答える 1

5

いろいろいじった後、ようやく何かを思い出しました。

のベースの最適化。

メンバーを獲得するとすぐAに、結果が変わります。ただし、何もない限り、コンパイラは の実際のレイアウトを生成する必要はありません。重要なのAは、各A「オブジェクト」が他のAオブジェクトとは異なるアドレスを持つことを保証することだけです。

したがって、コンパイラは、B(から継承するA) サブオブジェクトのアドレスを適切なアドレスとして単純に使用します。そして、BCが同じアドレスを持っていることがわかります (最初のベース + 両方とも仮想メソッドを持っています)。

一方、Aメンバーがある場合、または の最初のメンバーBが a の場合A(他の条件があります)、EBOは適用できなくなり、アドレスのジャンプに気付くでしょう。

于 2012-04-04T12:57:58.630 に答える