c++ - 为什么虚拟继承会导致指针偏移?

标签 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 = (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,因为它具有虚拟基数。这样,对于来说,编译器不可能将无vptrBase子对象放在Derived对象的最开始,因为它需要将vptr放置在内存中的该位置。

关于c++ - 为什么虚拟继承会导致指针偏移?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63482123/

相关文章:

c++ - GLM 矩阵中的旋转方向,使用四元数

c - 将节点添加到树问题

c++ - 转换到 `void` 的真正作用是什么?

c - iso_c_binding 使用来自 Fortran 的指针和数组调用 C 例程

c - 指针显式转换为 long long

java - 为什么JDK Map.get不支持返回值的类型推断

c++ - 如何处理这些旧式类型转换?

c++ - 使用 enable_if 匹配数字作为函数参数

c++ - Eigen:如何制作矩阵的深层拷贝?

c++ - 虚函数+带基类指针的STL容器