C++ 使用reinepret_cast解释对象地址

C++ 使用reinepret_cast解释对象地址,c++,casting,C++,Casting,以下代码给出的输出为136。但我不明白前两个地址的比较是如何相等的。感谢您对理解这一点的帮助。多谢各位 #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 { pu

以下代码给出的输出为136。但我不明白前两个地址的比较是如何相等的。感谢您对理解这一点的帮助。多谢各位

#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;
}
#包括
甲级
{
公众:
A():m_i(0){}
受保护的:
国际货币基金组织;
};
B类
{
公众:
B():mud(0.0){}
受保护的:
双m_d;
};
C类:公共A、公共B
{
公众:
C():m_C('a'){}
私人:
charm_c;
};
int main()
{
cd;
A*b1=&d;
B*b2=&d;
常数INTA=(重新解释投射(b1)=重新解释投射(&d))?1:2;
常数INTB=(b2==&d)?3:4;
const int c=(重新解释投射(b1)=重新解释投射(b2))?5:6;

std::cout当您使用多重继承(如示例中所示)时,第一个基类和派生类共享相同的基址。您从中继承的其他类根据前面所有类的大小按偏移量顺序排列。比较结果为真,因为
d
b1的基址是相同的

在您的情况下,如果
A
的大小为4字节,则
B
将从
A
+4字节的基址开始。执行
B*b2=&d;
时,编译器将计算偏移量并相应调整指针值


当您执行
b2==&d
时,在比较完成之前,会在
d
上执行从类型“C”到类型“B”的隐式转换。此转换调整指针值的偏移量,就像在赋值中一样。

这对于派生类来说非常典型(如
C
)在内存中进行布局,使其从两个基类(
A
B
)开始,因此
C
类型的实例的地址将与其第一个基类(即
A
)的实例的地址相同。

在这种继承中(当不涉及
virtual
时,)
C
的每个实例将具有以下布局:

  • 首先,将有
    A
    的所有成员(它只是
    mi
    ,一个4字节的整数)
  • 第二个将是
    B
    的所有成员(这只是
    mud
    ,一个8字节的双字节)
  • 最后是
    C
    本身的所有成员,它只是一个字符(1字节,
    m_C
当您将指向
C
实例的指针强制转换为
a
时,因为
a
是第一个父对象,所以不会进行地址调整,并且两个指针的数值将相同。这就是为什么第一次比较的计算结果为
true
(请注意,执行
重新解释强制转换()
在指针上不会引起调整,因此它总是给出指针的数值。将其转换为
void*
也会产生相同的效果,并且比较起来可能更安全。)

将指向
C
实例的指针强制转换为
B
将导致指针调整(4字节)这意味着
b2
的数值将不等于
&d
。但是,当您直接比较
b2
&d
时,编译器会自动将
&d
转换为
B*
,这会将数值调整4个字节。这是第二次比较also的计算结果为
true


第三个比较返回
false
,因为如前所述,将指向
C
实例的指针投射到
a
B
将产生不同的结果(投射到
a*
不会进行调整,而投射到
B*
则会进行调整。)你为什么要使用<代码> RealTytCase?在你的体系结构上,指针类型使用代码< CAR**/COD>,你期望什么?这不是来自实时应用程序。这是从C++测试中来的。我只是想了解RealExtCyCasp是如何解释这个特定情况下的地址的。关于为什么会产生这样的结果,布局依赖于编译器。您所描述的是典型的,但在任何地方都没有强制要求。@EJP是的!但是OP要求有人解释他在编译代码中看到的行为。我正在这样做。我不是说这是标准强制的;我只是解释如何他的程序的输出变成了现在的样子。