【问题标题】:Addresses, reinterpret_cast and multiple inheritance地址、reinterpret_cast 和多重继承
【发布时间】:2012-09-12 18:51:44
【问题描述】:

谁能解释以下代码的行为?

  1. 为什么在第一种情况下我们有b = 3,即b2 == &d 是真的?
  2. 为什么在案例 2 中正常?我打印了b2d的地址,它们是不同的。
#include <iostream>

using namespace std;

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

    cout << &d << endl;
    cout << b2 << endl;

    const int b = (b2 == &d) ? 3 : 4; ///Case1: b = 3;
    const int c = (reinterpret_cast<char*>(b2) == reinterpret_cast<char*>(&d)) ? 3 : 4; //Case 2:  c = 4;

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

    return 0;
}

【问题讨论】:

  • +1 ,因为这是一个很好的例子,很好地说明了多继承对指针的影响
  • +1 同样。很好的例子,尤其是没有虚拟的,可以真正让人们通过铃声。

标签: c++ pointers multiple-inheritance reinterpret-cast


【解决方案1】:

d 是 C 类型的。当你将指向 C 的指针转换为指向 B 的指针时,它会被调整为指向 C 的 B 子对象(如果不需要,多继承一般需要这种调整)对于 B,A 将有一个,因为 C 从 A 和 B 继承)。这样在赋值和比较的时候,调整就完成了。

在另外两次,&d 被转换为 void*(隐式)或 char*(带有 reinterpret_cast)并且没有进行任何调整(您明确要求不使用 reinterpret_cast 进行调整并且没有理由做转换为 void* 时进行调整,这只会无缘无故地使往返复杂化,对于 A),您将再次得到类似的结果,因此表示方式不同。

顺便说一句,如果您使用了reinterpret_cast&lt;B*&gt;(&amp;d),则不会再次进行任何调整,但是将结果用作 B* 会很快导致问题。

【讨论】:

    【解决方案2】:

    在情况 1 中,比较自动将 C 指针转换为 B 指针。在这种情况下,这意味着实际地址发生了变化,因为您使用多重继承,并且 B 在您的基类列表中排在第二位。更具体地说,指针必须偏移(至少)sizeof(A)。然而,在第二种情况下,没有执行这种自动转换,因此“A 前缀”使两个指针不相等。

    【讨论】:

    • 没有“自动演员表”之类的东西。强制转换是一种显式转换,它存在于源代码中。
    • 你这是什么意思?显然,案例 1 中存在向上转型,但并不明确。
    • 不明确的演员表根本就不是演员表。演员表可以是 C 风格、功能风格或新风格:(T)xT(x)static_cast&lt;T&gt;(x)...
    • 您对该声明有任何参考资料吗?请参阅programmers.stackexchange.com/questions/224493/… - “某些类型转换是隐式应用的,在其中一些类型中,编译器会发出警告。” - upCAST 显然是前者
    • 这是演员表的定义。这是一个语法结构。您要查找的词是conversion
    猜你喜欢
    • 2015-09-21
    • 2014-06-17
    • 1970-01-01
    • 1970-01-01
    • 2013-05-30
    • 2011-12-02
    • 2021-06-25
    • 2014-10-04
    • 2015-06-26
    相关资源
    最近更新 更多