对于多态类的对象,对象的地址和指向对象的指针是不是相同?
Posted
技术标签:
【中文标题】对于多态类的对象,对象的地址和指向对象的指针是不是相同?【英文标题】:Are address of object and pointer to object the same thing for an object of polymorph class?对于多态类的对象,对象的地址和指向对象的指针是否相同? 【发布时间】:2015-06-30 21:05:03 【问题描述】:我试图解决一个 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
谁能解释它的输出?我以为基指针指向基部分的一部分,所以它不是对象的真实地址。
谢谢。
【问题讨论】:
添加了输出 - 感谢您提供实际上是 MCVE 的 sn-p :) 【参考方案1】:pa
指向A
的c
子对象。 pb
指向 B
的子对象 c
。显然,它们指向内存中的不同位置(因此输出中的 6
)。
但是当它们与&c
比较时,&c
再次分别转换为A*
和B*
,从而指向相同的A
和B
子对象。
这里是为了说明c
在内存中的可能布局:
+------------------------+-------------+-------------------+
| A subobject | B subobject | Remainder of C |
+------------------------+-------------+-------------------+
^ &c is here ^ pb points here
^ pa also points here
【讨论】:
&c
分别转换为A*
和B*
,比较子对象地址。除非有人在没有人注意的情况下偷偷潜入魔法隐式向下转换。
你确定这个结构吗?或者这只是一个例子?
@molbdnilo 真的!我的错。
@GrigorApoyan 这是编译器在实践中最有可能生成的(假设没有进行虚拟继承)【参考方案2】:
背景
对象 C 在内存中看起来像这样
----------- <----- Start of the object
| A |
|---------| <----- Beginning of B implementation
| B |
|---------|
| C |
|_________| <----- End of the object
当您从派生类(例如 A* pa = &c)获取指向基类的指针时,该指针指向该对象的该类实现的开头。
所以这意味着 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)
这会给你一个编译错误,因为你需要将两个指针都转换为一个公共类型。
【讨论】:
以上是关于对于多态类的对象,对象的地址和指向对象的指针是不是相同?的主要内容,如果未能解决你的问题,请参考以下文章