为什么两个指针值不同?
Why don't the two pointer values be the same?
引用有效C++,Scott Meyer,第3版,第27项
class Base { ... };
class Derived: public Base { ... };
Derived d;
Base *pb = &d; // implicitly convert Derived* ⇒ Base*
这里我们只是创建一个指向派生类的基类指针对象但有时,两个指针值将不相同如果是这种情况,则在运行时将偏移应用于Derived*指针,以获得正确的Base*指针值。
为什么两个指针值不一样?如果是因为子对象和父对象在内存中的布局,那么下转换以后如何工作?
使用多重继承时总是会发生这种情况。
class Base1 { int a; };
class Base2 { double b };
class Derived : public Base1, public Base2 { ... };
Derived d;
Base1* pb1 = &d;
Base2* pb2 = &d;
现在&d
不可能同时等于pb1
和pb2
,因为否则pb1
将等于pb2
,这是不可能的,因为两个不相关类型的不同非空对象必须占用不同的内存区域。因此,至少在一种情况下,必须应用非零偏移。
在大多数具有单一继承的实现中,偏移量为零,但标准并没有强制要求这样做。
事实上,一个典型的实现只需在派生对象的开头布置基本对象:
++-----++
||Base ||
|+-----+|
|Derived|
+-------+
但当有多个基地时,一开始只能有一个基地:
++-----++
||Base1||
|+-----+|
||Base2||
|+-----+|
|Derived|
+-------+
下转换之所以有效,是因为偏移量是固定的,并且在编译时是已知的,所以在上转换或下转换时应用它没有问题。
一个例外是虚拟继承。对于虚拟基,偏移量在编译时是未知的。通常,派生对象包含一个指向其虚拟基的内部隐藏指针,因此上行可以工作。但是基不知道它的派生对象在哪里,所以向下转换不能工作,而且语言也不允许这样做。
当您有一个多态的继承树时,编译器要求每个对象以VMT(虚拟方法表)开头。如果基类是多态的,指针值就会匹配。但是如果你的基类是非多态的,而你的派生类是多态的,那么基类不会引入VMT,它是由树下的第一个多态类引入的。VMT将插入底座之前。现在指针值将不匹配。
相关文章:
- int数据类型的指针指向的是什么,如果是一个类的私有数据成员,我们创建了该类的两个对象?
- 创建一个棋盘格或"Interweave"两个链接列表。IE 更改两个链表的指针
- 是否可以使用非常量指针调用非常量函数,以及当两个unique_ptrs指向同一个对象时程序的行为方式?
- C++两个对象,其中包含指向同一数组不同部分的指针
- 比较两个 constexpr 指针不是 constexpr?
- 在两个.cpp文件之间定义全局类/结构指针
- 两个抽象类,派生自同一个基类.如何访问从一个抽象类到另一个抽象类的指针
- 如何在单个链表中交换两个节点的位置,只修改指针
- 如何仅考虑 *指针中的前两个元素
- 如果将两个相同的指针作为输入传递,memcmp 会做什么?
- 一个对象的两个指针.删除了一个指针,对象仍然存在
- C++如何同时删除位于两个向量中的 2 个指针?
- 如何将值添加到嵌套结构中,该结构在C++中有两个指针
- 比较两个指针时">="运算符的奇怪行为
- 根据下面的作者,如果两个指针指向不同的数组,则比较的第一个版本将未定义
- 有没有更好的方法来添加两个智能指针?
- 为什么我不能在同一行中定义两个相同类型的类的成员指针
- 为什么 fdump-class-hierarchy 为虚函数提供了两个指针 int vtable
- 两个类别的两个类,有指向另一堂课的指针
- 错误 :"+" 无法添加两个指针