天天看點

C++虛基類

可以使用作用域分辨符來來存放不同資料、進行不同操作,但也可以通過虛基類來維護一個成員副本。将共同基類設定為虛基類,這時不同路徑繼承過來的同名資料成員在記憶體中就隻有一個副本,同一個函數名也隻有一個映射。

虛基類成員在派生過程中和派生類一起維護同一個記憶體資料副本,這一點其實很好了解。

我們先來看一下沒有聲明虛基類的程式:

#include <iostream>
using namespace std;

class Base0{
    public:
        int var0;
        void fun0(){cout<<"Member of Base0"<<endl;}
};

class Base1:public Base0{
    public:                                //新增外部接口
        int var1;
};

class Base2:public Base0{
    public:                                //新增外部接口
        int var2;
};

class Derived:public Base1,public Base2{
    public:                                //新增外部接口
        int var;
        void fun(){cout<<"Member of Derived"<<endl;}
};

int main(){
    Derived d;
    d.var0=2;
    d.fun0();
    return 0;
}           

程式顯然無法成功運作,錯誤原因:

request for member 'var0'(fun0) is ambiguous(不明确的)

,因為Base1和Base2都有

var0

fun0()

,程式不知道你調用的是哪一個類繼承下來的,除非你用作用域分辯符來唯一辨別,寫成:

d.Base1::var0=2;
    d.Base1::fun0();
    d.Base2::var0=3;
    d.Base2::fun0();           

這樣Base1和Base2類下的資料就分開存儲了,當然我們也可以使用虛基類技術進行共同存儲,也就是這幾個類共用一個

var0

fun0

副本,能節省不少記憶體空間。

虛基類的聲明隻是在類派生過程中使用

virtual

關鍵字,代碼如下:

#include <iostream>
using namespace std;

class Base0{
    public:
        int var0;
        void fun0(){cout<<"Member of Base0"<<endl;}
};

class Base1:virtual public Base0{         
    public:                                //新增外部接口
        int var1;
};

class Base2:virtual public Base0{
    public:                                //新增外部接口
        int var2;
};

class Derived:public Base1,public Base2{
    public:                                //新增外部接口
        int var;
        void fun(){cout<<"Member of Derived"<<endl;}
};

int main(){
    Derived d;
    d.var0=2;                     //直接通路虛基類的資料成員
    d.fun0();                     //直接通路虛基類的函數成員
    return 0;
}           

這樣一來,程式就能成功運作:

C++虛基類

這時的Derived類中,通過Base1,Base2繼承來的基類Base0中成員

var0

fun0

隻有一份副本,改變

var0

的值,就相當于改變Base1,Base2中的

var0

的值了。

繼續閱讀