指向层次结构中类的指针的相等性

NPS*_*NPS 2 c++ inheritance pointers class memory-address

#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)

这段代码打印出来136表明第一个等式是真的,第二个也是第三个.因为pa并且pb都设置为&c前两个会有意义,但那么为什么第三个等式是假的?

我在Visual C++ 2012中运行此代码并使用调试器检查地址:

pa == 0x003bfc90
pb == 0x003bfc98
&c == 0x003bfc90
Run Code Online (Sandbox Code Playgroud)

显然,papb没有指向同一个地址,这意味着第三个等式应该是假的(并且是).但那么为什么前两个是真的呢?你能解释一下这里发生了什么吗?

Mik*_*our 7

两个指针确实具有不同的值,因为它们指向不同的子对象c; 这两个对象必须存在于不同的位置.

如果没有reinterpret_cast,则相等比较首先查找到相同指针类型的合适转换.这个转换&cC*B*通过修改指针值指向B的子对象c初始化时所施加完全相同的转换- pb.在转换之后,两个指针都具有相同的值,因此比较相等.

reinterpret_cast表示指针应转换为目标类型而不修改其值,无论该转换是否有意义.因此,在转换之后,指针仍然具有不同的值,并且比较不相等.