多重继承与虚继承 对象布局

一.多重继承

multi_derived

#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》, 其内存布局应该为:

base_mm

derived_mm

这里有3个问题:

1.第一个虚表中存有Base2的虚函数指针(图中红色椭圆框),但是通过pBase1的指针多态却访问不到

2.我们之所有称第一个vtable为主表,它属于整个Derived类的虚表,所以它的slot含有所有的虚函数指针;但是它又被第一个基类所共享

3.后面的各个vtable成为次表,其中slot的虚函数指针只和其对应基类相关的。并且访问这些虚函数需要this指针调整

二. 虚继承

《Inside C++ Object Model》P123使用virtual table offset strategy实现的,下面我们来探讨一下:

1. 简单的虚继承

simple_virtual_derived

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。

virtul_hir

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;
}

 

public-virtual

posted @ 2012-12-13 10:28  我不是geek  阅读(506)  评论(0编辑  收藏  举报