g ++实现如何处理这种情况?

时间:2012-04-04 10:16:04

标签: c++ visual-c++ gcc

这是this one的后续问题。

考虑这个例子:

#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

(这可以通过问题的accepted answer来解释)。

使用g ++,output is

pC == 0x96c8008
pA == 0x96c8008

所以,问题是,g ++的实现如何处理这种情况?当C应该有vtable时,地址是否相同? (我知道这是一个实现细节,不要说:)我对好奇心的这个实现细节很感兴趣。)

1 个答案:

答案 0 :(得分:5)

经过多次摆弄,我终于想起了什么。

空基优化

只要A获得成员,结果就会发生变化。但是,只要它没有,编译器就不需要为A生成实际布局,重要的是保证每个A“对象”将具有与其他任何A不同的地址{ {1}}对象。

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

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