c++ - 为什么两个指针值不相同?

标签 c++ pointers inheritance casting

引用 Effective C++,Scott Meyer,第 3 版,第 27 项

class Base { ... };
class Derived: public Base { ... };
Derived d;
Base *pb = &d; // implicitly convert Derived* ⇒ Base*

Here we’re just creating a base class pointer to a derived class object, but sometimes, the two pointer values will not be the same. When that’s the case, an offset is applied at runtime to the Derived* pointer to get the correct Base* pointer value.

为什么两个指针值不一样?如果是因为子对象和父对象在内存中是如何布局的,那么后面的downcast是如何工作的?

最佳答案

这在使用多重继承时总是会发生。

class Base1 { int a; };
class Base2 { double b };
class Derived : public Base1, public Base2 { ... };

Derived d;
Base1* pb1 = &d;
Base2* pb2 = &d;

现在 &d 不可能等于 both pb1pb2,否则 pb1 等于 pb2,这是不可能的,因为不相关类型的两个不同的非空对象必须占用不同的内存区域。因此,至少在一种情况下必须应用非零偏移。

在大多数具有单一继承的实现中,偏移量为零,但标准没有强制要求。

事实上,典型的实现会简单地将基础对象布置在派生对象的开头:

 ++-----++
 ||Base ||
 |+-----+|
 |Derived|
 +-------+

但是当有多个基地时,一开始只能走一个:

 ++-----++
 ||Base1||
 |+-----+|
 ||Base2||
 |+-----+|
 |Derived|
 +-------+

向下转型之所以有效,是因为偏移量是固定的并且在编译时已知,因此在向上转型或向下转型时应用它都没有问题。

一个异常(exception)是虚拟继承。对于虚拟基,偏移量在编译时是未知的。通常,派生对象包含一个指向其虚基的内部隐藏指针,因此向上转型可以工作。但是 base 不知道它的派生对象在哪里,所以向下转换无法工作,并且是语言不允许的。

关于c++ - 为什么两个指针值不相同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34368983/

相关文章:

c++ - OpenGL - 从 DisplayList 转换为使用 VBO

Javascript 继承 - 重叠基类变量

java - 对来自两个子类的对象的父类(super class)列表进行排序

c - 为什么我不能在 C 中取消引用指向结构的指针?

c++ - 我是如何打破继承的?

c++ - 为什么在使用此基本继承设置时会出现链接器错误?

c++ - TBB 流程图条件执行和多个输入和输出

c++ - 复古游戏: scaling all sprites or rather the entire canvas?

c - 输入数组后程序挂起

c - 如何不使指向数组 [0] 的指针在每个循环中修改数组 [0]