探索多态模型—菱形继承和菱形虚拟继承

来源:互联网 发布:网络不知名的女歌手 编辑:程序博客网 时间:2024/06/05 07:54

菱形继承
类AA被类BB和类CC重复继承:

这里写图片描述

class AA{public:    virtual void a(){ cout << "AA::a()" << endl; }    virtual void a1(){ cout << "AA::a1()" << endl; }public:    int _a;};class BB : public AA{public:    virtual void a(){ cout << "BB::a()" << endl; }    virtual void a2(){ cout << "BB::a2()" << endl; }    virtual void a3(){ cout << "BB::a3()" << endl; }public:    int _b;};class CC : public AA{public:    virtual void a(){ cout << "CC::a()" << endl; }    virtual void a1(){ cout << "CC::a1()" << endl; }    virtual void a4(){ cout << "CC::a4()" << endl; }public:    int _c;};class DD : public BB , public CC{public:    virtual void a(){ cout << "DD::a()" << endl; }    virtual void a2(){ cout << "DD::a2()" << endl; }    virtual void a3(){ cout << "DD::a3()" << endl; }    virtual void a5(){ cout << "DD::a5()" << endl; }public:    int _d;};typedef void(*FUNC) ();void Print(int *Vfptr){    cout << "虚表地址" << Vfptr << endl;    for (int i = 0; Vfptr[i] != 0; ++i)    {        FUNC f = (FUNC)Vfptr[i];        cout << "[" << i << "]" << endl;        f();    }    cout << endl;}int main(){    DD d;    int *Vfptr1 = (int*)(*(int*)&d);    int *Vfptr2 = (int*)(*((int*)&d+sizeof(BB)/4));    Print(Vfptr1);    Print(Vfptr2);    system("pause");    return 0;}

虚表的结果:

这里写图片描述

菱形继承总结:

会出现数据冗余和二义性问题
派生类会分别继承每个基类的虚函数表,并将自己的虚函数放在第一个虚函数表中
成员变量的顺序按照继承的关系排列

菱形虚拟继承
虚继承就是在类BB和类CC继承的时候加上virtual关键字

class AA{public:    virtual void a(){ cout << "AA::a()" << endl; }    virtual void a1(){ cout << "AA::a1()" << endl; }public:    int _a;};class BB : virtual public AA{public:    virtual void a(){ cout << "BB::a()" << endl; }    virtual void a2(){ cout << "BB::a2()" << endl; }    virtual void a3(){ cout << "BB::a3()" << endl; }public:    int _b;};class CC : virtual public AA{public:    virtual void a(){ cout << "CC::a()" << endl; }    virtual void a1(){ cout << "CC::a1()" << endl; }    virtual void a4(){ cout << "CC::a4()" << endl; }public:    int _c;};class DD : public BB , public CC{public:    virtual void a(){ cout << "DD::a()" << endl; }    virtual void a2(){ cout << "DD::a2()" << endl; }    virtual void a3(){ cout << "DD::a3()" << endl; }    virtual void a5(){ cout << "DD::a5()" << endl; }public:    int _d;};typedef void(*FUNC) ();void Print(int *Vfptr){    cout << "虚表地址" << Vfptr << endl;    for (int i = 0; Vfptr[i] != 0; ++i)    {        FUNC f = (FUNC)Vfptr[i];        cout << "[" << i << "]" << endl;        f();    }    cout << endl;}int main(){    DD d;    int *Vfptr1 = (int*)(*(int*)&d);    int *Vfptr2 = (int*)(*(int*)((char*)&d+sizeof(DD)-sizeof(AA)));    int *Vfptr3 = (int*)(*((int*)((char*)&d + sizeof(BB)-sizeof(AA))));    Print(Vfptr1);    Print(Vfptr2);    Print(Vfptr3);    system("pause");    return 0;}

这里写图片描述

注:当类BB,类CC都对类AA中的虚函数a()进行覆盖,会编译出错,出现二义性问题。这时类DD需要对虚函数a()进行重写,才可避免。