理解父/基类的c ++指针

Gio*_*Gio 14 c++ inheritance pointers

我被问到这个面试问题,我弄错了."输出是什么":我的答案是135,实际输出是136.这意味着指向两个父类的指针不相等,即使它们通过了等于子类的先前测试.我以为我理解了c ++指针,但这让我难以理解.虽然我想我知道发生了什么,但我不确定为什么.那里有哪些c ++专家可以提供技术解释?看来前两个比较本质上更合乎逻辑,而最后一个比较更具文字性......

#include <iostream>

class A
{
    public:
    A() : m_i(0) { }

    protected:
    int m_i;
};

class B
{
    public:
    B() : m_d(0.0) { }

    protected:
    double m_d;
};

class C
    : public A, public B
{
    public:
    C() : m_c('a') { }

    private:
    char m_c;
};

int main()
{
    C c;
    A *pa = &c;
    B *pb = &c;

    const int x = (pa == &c) ? 1 : 2;
    const int y = (pb == &c) ? 3 : 4;
    const int z = (reinterpret_cast<char*>(pa) == reinterpret_cast<char*>(pb)) ? 5 : 6;

    std::cout << x << y << z << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Kev*_*vin 8

也许如果你打印出来pa,pb它会更清楚发生了什么.

std::cout << "A: " << pa << std::endl;
std::cout << "B: " << pb << std::endl;
std::cout << "C: " << &c << std::endl;
Run Code Online (Sandbox Code Playgroud)

在最后运行这个main给了我

A: 0xbfef54e0
B: 0xbfef54e4
C: 0xbfef54e0
Run Code Online (Sandbox Code Playgroud)

(你的输出可能会有所不同,重要的是它们并不完全相同)

这是因为C对象在内存中的表示方式.由于a C既是a又是Aa B,它需要拥有每个部分的数据成员.真正的布局C是这样的(忽略填充):

int    A::m_i;
double B::m_d;
char   C::m_c;
Run Code Online (Sandbox Code Playgroud)

将a转换为a C*A*,编译器知道该A部件从偏移量0开始,因此指针值不会改变.为了C*B*它需要抵消sizeof(int)(加垫).这种偏移处理是自动完成的,用于计算xy.对于z它被忽略,因为您使用reinterpret_cast