我知道,由于内存布局的原因,在将派生类指针转换为基类指针时,多重继承和虚函数会导致指针偏移。
但是我不知道为什么虚拟继承也会引起这种影响?我对虚拟继承的唯一了解是防止同一类的多个实例。
下面是我的代码。
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;
}
最佳答案
以下代码
#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);
}
在我的机器(Debian / g++)上产生以下输出:Base offset: 16
a offset: 16
Derived offset: 0
b offset: 8
因此,对象的布局是这样的:+------+------+------+
| vptr | b | a |
+------+------+------+
| Base |
| Derived |
如您所见,编译器尚未为vptr
类分配Base
。这是标准要求的,因为Base
是没有任何虚拟功能的POD(普通旧数据)类型。 Derived
类必须包含vptr
,因为它具有虚拟基数。这样,对于来说,编译器不可能将无vptr
的Base
子对象放在Derived
对象的最开始,因为它需要将vptr
放置在内存中的该位置。
关于c++ - 为什么虚拟继承会导致指针偏移?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63482123/