C++菱形继承的内存模型(VS2017环境)

1.菱形继承简要介绍

  首先简单介绍一下菱形继承,由于支持多继承,因此会产生菱形继承这种情况(如图1所示)。在这种情况下,如果类的对象 想要访问成员 ,如果直接通过 访问,由于编译器不知道应该是找类 继承的成员 ,还是 ,由此产生二义性,编译报错(注: 必须明确指定,比如 这样才能正确通过编译)。

图1.菱形继承示意图

  为了解决这个问题,C++提供了一种虚继承的机制,在这种机制下,子对象只保留父对象共有成员的一份拷贝,因此不会存在二义性的问题。下面是我在VS2017-x86模式下,反汇编后,将其内存布局简要刻画出来(图2)。

2.菱形继承内存布局刻画
  • 源码示例
#include
using namespace std;

class A{
public:
    int a;
    A(int _a):a(_a){};
    virtual void show() { cout << "This is A::show()." << endl; }
}

class B: virtual public A{
public:
    int b;
    B(int _a, int _b):A(_a),b(_b){};
    virtual void show(){ cout << "This is B::show()." << endl;  }
}

class C: virtual public A{
public:
    int c;
    C(int _a, int _c):A(_a),c(_c){};
    virtual void show(){ cout << "This is C::show()." << endl; }
}

class D: public B, public C{
public:
    int d;
    D(int _a, int _b, int _c, int _d):A(_a),B(_a,_b),C(_a,_c),d(_d){};
    virtual void show(){ cout << "This is D::show()." << endl; }
}
  • 其内存布局如图2所示,其中每个虚继承的子类存在一个虚基类表指针,该指针指向的地方存在一个偏移值 ,该偏移值 指示当前类中虚表指针(当没有虚函数时,指向虚基类数据成员)的位置。
    图2. 菱形继承内存布局示意图
3.总结
  • 在存在虚继承的类中,会存在虚基类指针,该指针指向的地方存放一个偏移,这个偏移为虚基类指针到虚基类数据的偏移;
  • 子类只保存一份虚基类的数据对象,这样可以防止二义性;

你可能感兴趣的:(C++菱形继承的内存模型(VS2017环境))