C++ 为什么虚拟继承会导致指针偏移?
我知道,由于内存布局的原因,在将派生类指针强制转换为基类指针时,多个继承和虚拟函数会导致指针偏移 然而,我不明白为什么虚拟继承也会造成这种影响?关于虚拟继承,我只知道防止同一类的多个实例 下面是我的代码C++ 为什么虚拟继承会导致指针偏移?,c++,pointers,casting,virtual-inheritance,C++,Pointers,Casting,Virtual Inheritance,我知道,由于内存布局的原因,在将派生类指针强制转换为基类指针时,多个继承和虚拟函数会导致指针偏移 然而,我不明白为什么虚拟继承也会造成这种影响?关于虚拟继承,我只知道防止同一类的多个实例 下面是我的代码 class X { public: int i; }; class Y :virtual public X { int j; public: void vf(){}; }; int main() { Y* py = new Y; X* px =
class X
{
public:
int i;
};
class Y :virtual public X
{
int j;
public:
void vf(){};
};
int main()
{
Y* py = new Y;
X* px = (X*)py;
cout<<py<<endl;
cout<<px<<endl;
}
X类
{
公众:
int i;
};
Y类:虚拟公共X
{
int j;
公众:
void vf(){};
};
int main()
{
Y*py=新的Y;
X*px=(X*)py;
cout以下代码
#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
struct Base {
long a;
};
struct Derived : virtual public Base {
long b;
};
int main() {
Derived object;
intptr_t reference = (intptr_t)&object;
printf("Base offset: %" PRIdPTR "\n", (intptr_t)(Base*)&object - reference);
printf("a offset: %" PRIdPTR "\n", (intptr_t)&object.a - reference);
printf("Derived offset: %" PRIdPTR "\n", (intptr_t)(Derived*)&object - reference);
printf("b offset: %" PRIdPTR "\n", (intptr_t)&object.b - reference);
}
因此,对象的布局如下所示:
+------+------+------+
| vptr | b | a |
+------+------+------+
| Base |
| Derived |
如您所见,编译器没有将vptr
分配给类Base
。这是标准所要求的,因为Base
是POD(普通旧数据)键入时不带任何虚拟功能。派生的
类必须包含一个vptr
,因为它有一个虚拟基。因此,编译器不可能将vptr
-less基
子对象放在派生的
对象的最开头,因为它需要在内存中的该位置请不要添加不相关的标记。这显然不是C代码。px的值与py的值不同“也可能导致此问题?”:这不是问题,是吗?请解释为什么在这种情况下,您认为指针偏移是一个问题。这是一件事,表明存在(有效的)问题在aY
中只有一个X
,另外一个建议X
和Y
应该在同一个地址。想象一下,如果存在多个Y
的X1
,X2
等虚拟基,会发生什么情况-你真的建议aY
的地址应该是相等的吗l到所有X1
、X2
等的地址,以获得更多信息:同时打印对象内两个变量的地址(或相对偏移量)。间隙将显示vtable指针的位置。vptr(如果存在)不必先来。它必须在<代码>派生对象中有固定的偏移量,以便编译器能够找到它。在旧的日子里,VPTR的位置是不同的。当微软引入COM时,是COM要求VPTR在前面,而C++编译器没有做过,所以它们会工作。使用COM时。@PeteBecker我记得在(经典)Mac OS(68000或第一代PowerPC)上,Metrowerks CodeWarrior在对象的一端有vptr,在另一端有Symantec“THINK C”/C++(但我不记得哪个是哪个)@curiousguy-Borland的编译器最初将vtable放在基类数据的末尾。当我们添加COM支持时,它移到了前面。
+------+------+------+
| vptr | b | a |
+------+------+------+
| Base |
| Derived |