9

任何人都可以解释以下代码的行为吗?

  1. 为什么我们b = 3在第一种情况下,即是真b2 == &d的?
  2. 为什么在案例 2 中可以?b2和的地址我已经打印出来了d,它们是不同的。
#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;
}
4

2 回答 2

9

d 是 C 类型的。当你将指向 C 的指针转换为指向 B 的指针时,它会被调整为指向 C 的 B 子对象(如果 B 不需要这种调整,一般需要多重继承, A 会有一个,因为 C 继承自 A 和 B)。因此,在分配和比较时,调整完成。

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

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

于 2012-09-20T12:12:01.633 回答
3

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

于 2012-09-20T12:12:16.847 回答