reinterpret_cast用于C ++中的多继承

时间:2014-05-01 10:21:15

标签: c++ inheritance casting reinterpret-cast

在做一些c ++练习时,我发现了一个与多继承和强制转换相关的有趣例子。

我无法弄清楚原因 reinterpret_cast<char*>(b1) is not equal reinterpret_cast<char*>(b2)

这是一个简单的程序,我在上面提到过:

#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 d;
    A *b1 = &d;
    B *b2 = &d;

    const int a = (reinterpret_cast<char*>(b1) == reinterpret_cast<char*>(&d)) ? 1 : 2;
    const int b = (b2 == &d) ? 3 : 4;
    const int c = (reinterpret_cast<char*>(b1) == reinterpret_cast<char*>(b2)) ? 5 : 6;

    std::cout << a << b << c << std::endl;

    return 0;
}

当reinterpret_cast(b1)等于reinterpret_cast(&amp; d)时,你能否为这个topis提供任何评论以帮助我弄清楚为什么reinterpret_cast(b1)不等于reinterpret_cast(b2)?

2 个答案:

答案 0 :(得分:3)

为什么应该地址相等? *b1A类型的对象,*b2B类型的对象。它们是不同的对象(尽管不是完整的对象),并且没有一个是另一个的子对象,所以它们完全可以预期它们具有不同的地址 - 实际上,它们只有这样才能拥有相同的地址,如果至少有一个他们的类型是空的(在你的代码中不是这种情况)。

答案 1 :(得分:3)

基类子对象必须以某种方式安排在最派生对象内的内存中。在你的情况下,编译器似乎这样做了:

C---------------+
|A---+ B---+    |
||m_i| |m_d| m_c|
|+---+ +---+    |
+---------------+

这意味着A子对象从与整个C对象相同的地址开始,但B子对象的移动大小为A(即大小)一个int)。

B *b2 = &d;

因为b2是指向B的指针,所以它指向B子对象,因此它指向的物理地址是移位的。

至于为什么b2 == &d成立 - 指向不同类型的指针永远无法进行相等性比较。但是指向派生类的指针可以隐式转换为指向基类的指针。因此b2 == &d实际上已转换为b2 == static_cast<B*>(&d),其中包含b2。请注意,隐式转换自然会应用移位,并且它与您首先获得{{1}}时使用的转移相同。

您可以尝试重新组织继承顺序或删除/添加一些数据成员,以了解它如何影响布局。