多態和多態對象模型

1 單繼承的多態,以以下代碼爲例

class A
{
public:
    virtual void f1()
    {
        cout<<"A::f1"<<endl;
    }
    virtual void f2()
    {
        cout<<"A::f2"<<endl;
    }
    void f3()
    {
        cout<<"A::f3"<<endl;
    }
};

class B :public A
{
public:
    virtual void f1()
    {
        cout<<"B::f1"<<endl;
    }
    virtual void f2()
    {
        cout<<"B::f2"<<endl;
    }
    void f3()
    {
        cout<<"A::f3"<<endl;
    }
};


int main()
{
    A* a;
    B b;
    a=&b;
    a->f1();
    a->f2();
    a->f3();

    return 0;
}

這裏寫圖片描述
2.繼承的多態以以下代碼爲例

#include<iostream>
using namespace std;


class A
{
public:
    virtual void f1()
    {
        cout<<"A::f1"<<endl;
    }

public:
    int _a;
};
class B
{
public:
    virtual void f2()
    {
        cout<<"B::f2"<<endl;
    }
public:
    int _b;
};
class C:public B,public A
{
public:
    virtual void f3()
    {
        cout<<"C::f3"<<endl;
    }
public:
    int _c;
};
typedef void(*VFUNC)();

void PrintVTable(void* vtable)
{
    printf("vtable:0x%p\n", vtable);
    VFUNC* array = (VFUNC*)vtable;
    for (size_t i = 0; array[i] != 0; ++i)
    {
        printf("vtable[%d]:0x%p->", i,array[i]);
        array[i]();
    }
    cout<<"================================"<<endl;
}
int main()
{
    A a;
    B b;
    C c;
    PrintVTable(*((int**)&c));
    return 0;
}

這個多繼承說明了基類有虛表時,派生類會繼承基類的虛數表,並且是先繼承誰,就會把自己的虛函數存儲在誰的虛表中,我們通過調用監視窗口和打印虛表來看清這一問題。
這裏寫圖片描述
所以說C有兩個虛表。
3.菱形繼承

class A
{
public:
    virtual void f1()
    {
        cout<<"A::f1"<<endl;
    }

public:
    int _a;
};
class B:public A
{
public:
    virtual void f1()
    {
        cout<<"B::f1"<<endl;
    }
    virtual void f2()
    {
        cout<<"B::f2"<<endl;
    }
public:
    int _b;
};
class C:public A
{
public:
    virtual void f3()
    {
        cout<<"C::f3"<<endl;
    }
public:
    int _c;
};
class D:public B,public C
{
public:
    virtual void f1()
    {
        cout<<"D::f1"<<endl;
    }
    virtual void f4()
    {
        cout<<"D::f4"<<endl;
    }
public:
    int _d;

};


typedef void (*V_FUNC)();  
void PrintVTable(int vtable)  
{  
    int* VfArray = (int*)vtable;  
    printf("vtable:0x%p\n",VfArray);  
    for(int i = 0;VfArray[i] != 0;++i)  
    {  
        printf("vfun[%d]:0x%p->",i,VfArray[i]);  
        V_FUNC f = (V_FUNC)VfArray[i];  
        f();  
    }  
    cout<<"*********************************"<<endl;  
}  
int main()
{
    A a;
    B b;
    C c;
    D d;
    d.B::_a=1;
    d.C::_a=2;
    d._b=3;
    d._d=4;

    PrintVTable(*((int*)&d));  
    PrintVTable(*(int*)((char*)&d+12));  

    return 0;
}

這裏寫圖片描述
菱形繼承也符合單繼承和多繼承的規律
總結:
當基類有虛函數即有虛表時,派生類就會繼承其虛表。一個只有虛表的類就是4個字節大小,就是一個指針的大小。

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