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++,输出为

PC == 0x96c8008
pA == 0x96c8008

那么,问题来了,g++的实现是如何处理这种情况的呢?C当应该有一个 vtable时,是什么使地址相同?(我知道这是一个实现细节,不要这么说:)出于好奇,我对这个实现细节感兴趣)。

4

1 回答 1

5

折腾了好久,我终于想起了什么。

基优化

一拿到会员,结果就A变了。但是,只要它没有,编译器就不需要为 生成真正的布局A,重要的是保证每个A“对象”将具有与任何其他A对象不同的地址。

因此,编译器只需将B子对象(继承自A)的地址用作合适的地址。事实证明,B并且C具有相同的地址(第一个基数 + 都具有虚拟方法)。

另一方面,如果A有一个成员,或者如果第一个成员B是 a A(还有其他条件),那么EBO就不能再适用了,您会注意到地址发生了跳跃。

于 2012-04-04T12:57:58.630 回答