问题描述
我知道,由于内存布局的原因,在将派生类指针转换为基类指针时,多重继承和虚函数会导致指针偏移。
但是我不知道为什么虚拟继承也会导致这种情况?我对虚拟继承的唯一了解是防止同一类的多个实例。
下面是我的代码。
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;
}
解决方法
以下代码
npm start
在我的机器(Debian / g ++)上产生以下输出:
node001 gpu,compute,randomgroup
node002 compute,randomgroup
因此,对象的布局是这样:
#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);
}
如您所见,编译器尚未为类Base offset: 16
a offset: 16
Derived offset: 0
b offset: 8
分配+------+------+------+
| vptr | b | a |
+------+------+------+
| Base |
| Derived |
。这是标准要求的,因为vptr
是POD(普通旧数据)类型,没有任何虚拟功能。 Base
类必须包含Base
,因为它具有虚拟基数。因此,编译器不可能将Derived
少的vptr
子对象放在vptr
对象的最开始,因为它需要放置{{1} }在内存中的那个位置。