多重继承与虚继承 对象布局
一.多重继承
#include <iostream>
using namespace std;
class Base1
{
public:
Base1(){ cout << "Base1::Base1()" << endl;}
virtual ~Base1(){ cout << "Base1::~Base1()" << endl;}
virtual void speakClearly(){ cout << "Base1::speakClearly()" << endl;}
virtual Base1 *clone() const { cout << "Base1::clone()" << endl;}
protected:
float data_Base1;
};
class Base2
{
public:
Base2(){ cout << "Base2::Base2()" << endl;}
virtual ~Base2(){ cout << "Base2::~Base2()" << endl;}
virtual void mumble(){ cout << "Base2::mumble()" << endl;}
virtual Base2 *clone() const{ cout << "Base2::clone()" << endl;}
protected:
float data_Base2;
};
class Derived : public Base1, public Base2
{
public:
Derived(){ cout << "Derived::Derived()" << endl;}
virtual ~Derived(){ cout << "Derived::~Derived()" << endl;}
virtual Derived *clone() const { cout << "Derived::clone()" << endl;}
protected:
float data_Derived;
};
int main()
{
Base1 *pBase1=new Derived;
pBase1->clone();
pBase1->speakClearly();
//pBase1->mumble();//complie-time error
delete pBase1;
cout << "-----------------------------------" << endl;
Base2 *pBase2=new Derived;
pBase2->clone();
pBase2->mumble();
delete pBase2;
system("PAUSE");
return 0;
}
按照《Inside C++ Objecet Model》, 其内存布局应该为:
这里有3个问题:
1.第一个虚表中存有Base2的虚函数指针(图中红色椭圆框),但是通过pBase1的指针多态却访问不到
2.我们之所有称第一个vtable为主表,它属于整个Derived类的虚表,所以它的slot含有所有的虚函数指针;但是它又被第一个基类所共享
3.后面的各个vtable成为次表,其中slot的虚函数指针只和其对应基类相关的。并且访问这些虚函数需要this指针调整
二. 虚继承
《Inside C++ Object Model》P123使用virtual table offset strategy实现的,下面我们来探讨一下:
1. 简单的虚继承
class Point2d
{
public:
Point2d(float x=0.0, float=1.0);
virtual ~Point2d();
virtual void mumble();
virtual float z();
//...
protected:
float _x, _y;
};
classs Point3d : public virtual Point2d
{
public:
Point3d(float x=0.0, float y=0.0, float z=0.0);
~Point3d();
virtual float z();
protected:
float _z;
};
2. 多重继承情况下的虚继承:只有虚继承才会生成新虚指针,如果Vertex3D也是虚继承Vertex和Point3D,则Vertex3D也会产生一个vptr。
class Point2d
{
public:
virual 2d_func(){}
protected:
float _x, _y;
};
class Vertex : public virtual Point2d
{
public:
virtual ver_func(){}
protected:
Vertex *next;
};
class Point3d : public virtual Point2d
{
public:
virual 3d_func(){}
protected:
float _z;
};
class Vertex3d : public Vertex, public Point3d
{
public:
virtual ver3d_func(){}
protected:
float mumble;
}