为什么指向同一个对象的指针具有不同的值?

10
我有这段代码:
#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;

    std::cout << (long)b1 << std::endl <<(long)b2<< std::endl;
}

编译并运行后,它会生成以下输出:

140734705182320
140734705182328

为什么指向同一地址(&d)的不同指针具有不同的值尚不完全清楚。

提前致谢。


因为它们指向同一个对象。b1指向一个A对象,b2指向一个B对象。两个类都不是彼此的子类型,因此也不能指向彼此的子对象。 - user395760
1
指针确实具有不同的地址,但这并不是您的程序所展示的。它展示的是它们存储不同的地址。 - Benjamin Lindley
你应该将指针值转换为 void* 而不是 long,以便打印。 - Keith Thompson
请使用 static_cast,而不是 C 风格的转换。 - Christian Hackl
1个回答

12

C对象的内存布局将类似于:

A base_object_1;
B base_object_2;
char m_c;

这两个基础对象的地址不同;A通常与完整对象具有相同的地址,但是B通常没有。除非至少有一个为空,否则它们不能拥有相同的地址。

因此,将指向完整对象的指针转换为指向其中一个基本对象的指针必须更改指针值,以便指向正确的地址。


值得注意的是,C* b3 = &d; 将指向与 b1 相同的地址。为了完全清楚,如果将示例更改为 B 继承自 A(并且 C 仅直接继承自 B),则 b1b2b3 具有相同的值。 - CompuChip
@CompuChip:确实;不过这两点都不能由语言来保证。 - Mike Seymour
没错,你也不需要关心。你使用 A 指针指向 C 实例的原因是,你可以访问它的 A 接口,而不需要知道它的运行时类型 - 而不是你可以对它进行指针魔法(又称算术) :) - CompuChip

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接