C++對象模型(二)多繼承

3.多繼承模型
看下面代碼:

class Base1
{
public:
    Base1():_b1(1)
    {}
    virtual void fun1()
    {
        cout<<"Base1::fun1()"<<endl;
    }
    virtual void fun2()
    {
        cout<<"Base1::fun2()"<<endl;
    }

private:
    int _b1;
};

class Base2
{
public:
    Base2():_b2(2)
    {}
    virtual void fun3()
    {
        cout<<"Base2::fun3()"<<endl;
    }
    virtual void fun4()
    {
        cout<<"Base2::fun4()"<<endl;
    }
private:
    int _b2;
};

class Derive:public Base1,public Base2
{
public:
    Derive():_d(3)
    {}
    virtual void fun2()
    {
        cout<<"Derive::fun2()"<<endl;
    }
    virtual void fun4()
    {
        cout<<"Derive::fun4()"<<endl;
    }
    virtual void fun5()
    {
        cout<<"Derive::fun5()"<<endl;
    }
private:
    int _d;
};

int main()
{
    Base1 b1;
    Base2 b2;
    Derive d;
    cout<<sizeof(d)<<endl;//20
    return 0;
}

這裏d的大小爲什麼是20呢,下面給出d的對象模型:
這裏寫圖片描述
看下內存:
這裏寫圖片描述

用下面函數打印之:(注:VS2008環境)

void test()
{
    Derive d;
    pfun* p = (pfun*)*((int*)(&d));

    PrintVirtual(p);
    p-=4;
    PrintVirtual(p);
}

這裏寫圖片描述

多重繼承編譯器是怎麼做的呢?
1)先將基類的虛表中的內容各自拷貝一份,有幾個基類,就有幾個虛表
2)如果派生類對基類中的虛函數進行重寫,就是用派生類中的虛函數替換相同偏移位置的基類虛函數
3)派生類將自己新增的虛函數放在第一個基類虛表後面

4.含虛繼承的多繼承(菱形繼承)

class Base
{
public:
    Base():_b(1)
    {}
    virtual void fun1()
    {
        cout<<"Base::fun1()"<<endl;
    }
private:
    int _b;
};
class C1:public virtual Base
{
public:
    C1():_c1(2)
    {}
    virtual void fun2()
    {
        cout<<"C1::fun2()"<<endl;
    }
    virtual void fun3()
    {
        cout<<"C1::fun3()"<<endl;
    }
private:
    int _c1;
};
class C2:public virtual Base
{
public:
    C2():_c2(3)
    {}
    virtual void fun4()
    {
        cout<<"C1::fun4()"<<endl;
    }
    virtual void fun5()
    {
        cout<<"C1::fun5()"<<endl;
    }
private:
    int _c2;
};
class Derive:public C1,public C2
{
public:
    Derive():_d(4)
    {}
    virtual void fun3()
    {
        cout<<"Derive::fun3()"<<endl;
    }
    virtual void fun5()
    {
        cout<<"Derive::fun5()"<<endl;
    }
    virtual void fun6()
    {
        cout<<"Derive::fun6()"<<endl;
    }
private:
    int _d;
};
int main()
{
    cout<<sizeof(Derive)<<endl;//36
    return 0;
}

下面給出Derive的對象模型:
這裏寫圖片描述
用下面函數打印驗證之:

void test()
{
    Derive d;
    pfun* p = (pfun*)*((int*)(&d));

    PrintVirtual(p);
    p-=4;
    PrintVirtual(p);
    p-=3;
    PrintVirtual(p);

}

這裏寫圖片描述
C1,C2的虛表生成機制和前面類似多繼承一樣。
菱形虛擬繼承派生類虛表:
1)覆蓋基類的的虛函數
2)如果派生類新增虛函數,則新增添到虛表後面

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章