对于多态class的对象,对象的地址和指向对象的指针是一回事吗?

Are address of object and pointer to object the same thing for an object of polymorph class?

我正在尝试解决 C++ 测试,并看到了这个问题。

#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 c;
    A *pa = &c;
    B *pb = &c;

    const int x = (pa == &c) ? 1 : 2;
    const int y = (pb == &c) ? 3 : 4;
    const int z = (reinterpret_cast<char*>(pa) == reinterpret_cast<char*>(pb)) ? 5 : 6;

    std::cout << x << y << z << std::endl;

    return 0;
}

Output :

136

谁能解释一下它的输出?我以为base指针指向的是base部分的部分,所以不是对象的真实地址

谢谢。

pa 指向 cA 子对象。 pb 指向 cB 子对象。显然,它们指向内存中的不同位置(因此输出中的 6)。

但是当它们与&c比较时,&c再次分别转换为A*B*,从而指向相同的AB 子对象。

为了说明 c 在内存中的可能布局:

+------------------------+-------------+-------------------+
| A subobject            | B subobject | Remainder of C    |
+------------------------+-------------+-------------------+
^ &c is here             ^ pb points here
^ pa also points here

背景

对象 C 在内存中看起来像这样

    -----------  <----- Start of the object
    |    A    |
    |---------|  <----- Beginning of B implementation
    |    B    |
    |---------|
    |    C    |
    |_________|  <----- End of the object

当您从派生的 class(例如 A* pa = &c)获取指向基 class 的指针时,该指针指向该 class 实现的开头那个对象。

所以这意味着A*将指向A的开头(恰好是对象的开头)而B*将指向B的开头。注意C*不会指向的开头C因为它知道C是从A和B派生出来的,它会指向对象的开头。

为什么?

因为当你调用pb->someFunction()时,它实际上是把指向B的指针加上一些预先计算好的偏移量然后执行。如果 pb 指向 A 的开头,那么它将在 A 内部结束。预先计算的偏移量是必要的,因为您不知道 pb 实际指向什么(是 C,是 "D",还是只是普通的老 B?)。这种方法允许我们始终依赖偏移量来查找函数。

这就是您的代码真正做的事情

((A*)pa == (A*)&c) // Obviously true, since we defined it as such above.
((B*)pb == (B*)&c) // Obviously true, since we defined it as such above.
(reinterpret_cast<char*>(pa) == reinterpret_cast<char*>(pb)) // We know pa and pb point to different places in memory. If we cast them both to char*, they will obviously not be equivalent.

一个有趣的尝试是

if (pa == pb)

这会给你一个编译错误,因为你需要将两个指针转换为一个通用类型。