【问题标题】:reinterpret_cast used in multi inheritance in C++reinterpret_cast 用于 C++ 中的多继承
【发布时间】:2014-06-17 19:44:08
【问题描述】:

在做一些 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;
}

您能否为此主题提供任何 cmets 以帮助我弄清楚为什么当 reinterpret_cast(b1) 等于 reinterpret_cast(&d) 时 reinterpret_cast(b1) 不等于 reinterpret_cast(b2)?

【问题讨论】:

  • 更改继承 A 和 B 的顺序,并检查结果。这是否有助于您了解正在发生的事情?

标签: c++ inheritance casting reinterpret-cast


【解决方案1】:

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

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

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

B *b2 = &d;

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

至于为什么b2 == &amp;d 成立——指向不同类型的指针永远无法比较是否相等。但是指向派生类的指针可以隐式转换为指向基类的指针。所以b2 == &amp;d实际上转换为b2 == static_cast&lt;B*&gt;(&amp;d),它成立。请注意,隐式转换自然会应用移位,它与您最初用于获取b2 的转换相同。

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

【讨论】:

  • 好吧,这听起来很合理,但如果是这样,为什么 b2 == &d 是 TRUE 而 reinterpret_cast(b2) == reinterpret_cast(&d) 是 FALSE 那么呢?
  • @Leopoldo:因为你的假设是错误的 ;) 具体来说,b2 == &amp;d 不是(void*)b2 == (void*)&amp;d,而是将&amp;d 转换B*,这适用于偏移量,然后才像 b2 == static_cast&lt;B*&gt;(&amp;d) 那样比较。
  • @Leopoldo 我已经扩展了答案。
【解决方案2】:

为什么应该地址是相等的? *b1A 类型的对象,*b2B 类型的对象。它们是不同的对象(尽管不是完整的对象),并且都不是另一个的子对象,因此完全可以期望它们具有不同的地址-实际上,它们具有相同地址的唯一方法是至少其中一个它们的类型是空的(在您的代码中不是这种情况)。

【讨论】:

    猜你喜欢
    • 2012-09-12
    • 2015-01-02
    • 2014-12-26
    • 2011-02-12
    • 2018-12-11
    • 2017-03-31
    • 2011-03-29
    • 1970-01-01
    相关资源
    最近更新 更多