有人可以解释以下代码的行为吗?
b = 3
,即b2 == &d
是真的?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;
}
答案 0 :(得分:9)
d是C类型。当你将指向C的指针转换为指向B的指针时,它会被调整,使它指向C的B子对象(如果不需要,那么通常需要这样的ajustement具有多个继承性对于B,将有一个用于A,因为C继承自A和B)。因此,在分配和比较时,完成调整。
在另外两次,&amp; d被转换为void *(隐式)或char *(带有reinterpret_cast)并且没有进行任何调整(你明确要求使用reinterpret_cast进行调整,没有理由在转换为void *时进行调整,它只会使往返复杂化,没有充分的理由,你再次得到类似的结果A)所以表示不同。
顺便说一下,如果您使用过reinterpret_cast<B*>(&d)
,则不会再次进行调整,但将结果用作B *会导致问题迅速发生。
答案 1 :(得分:3)
在情况1中,比较自动将C指针强制转换为B指针。在这种情况下,这意味着实际地址会发生变化,因为您使用了多重继承,而B在基类列表中排名第二。更具体地说,指针必须偏移(至少)sizeof(A)。然而,在第二种情况下,没有执行这样的自动转换,因此“A前缀”使得两个指针不相等。