1. 程式人生 > >【C++學習筆記】虛基類(二)

【C++學習筆記】虛基類(二)

上一期由於寫累了,偷了點懶,就沒把注意點放完,這次繼續。
(3)若同一層次中同時包含虛基類和非虛基類,應該先呼叫虛基類,再呼叫非虛基類。(同一層中:同一級的繼承中)
(4)對於多個虛基類,建構函式執行順序任然是先左後右,先上後下。
(5)對於非虛基類,建構函式的執行順序也是先左後右,先上後下。
(6)若虛基類由非虛基類派生而來,則仍然先呼叫基類建構函式,再呼叫派生類建構函式。

這四點體現了在同級情況下,基類、虛基類優先,先構建好基類體系,再往外派生具體成員。

虛基類的建構函式:

#include<iostream.h>
	class base {
	public:
          base(int sa)
	    {   a=sa;
	        cout<<"Constructing base"<<endl;   }
         private:
	    int a;
	};
	class base1:virtual public base{
	public:
	    base1(int sa,int sb):base(sa)
	    {    b=sb;
	         cout<<"Constructing baes1"<<endl;	    }
         private:
	    int b;
	};
	class base2:virtual public base{
	public:
	    base2(int sa,int sc):base(sa)
	    {   c=sc;
	        cout<<"Constructing baes2"<<endl;   }
	private:
	    int c;
	};
	
class derived:public base1,public base2{
public:
    derived(int h,int d):base1(h),base2(d){cout<<"derived a ="<<a+d<<endl; }
};
int main(){
    derived obj(5,8);
    return 0;
}

我們關注derived(int h,int d):base1(h),base2(d),
1.在C++中規定:虛基類子物件是由最派生類的建構函式進行初始化的。
(主函式中直接用於定義變數的類叫做最派生類,比如在例子中,derived直接在主函式中用於定義變數obj,所以它是最派生類。)
在本例中,base1和 base2的建構函式的呼叫是在用最派生類derived定義obj時開始呼叫的。

2.如果一個派生類有一個直接或間接的虛基類,那麼派生類的建構函式的成員初始列表中必須列出對虛基類建構函式的呼叫,如果為被列出,則表示使用該虛基類的預設建構函式來初始化派生類物件中的虛基類物件。
例子:

class base2:virtual public base{
public:
    base2(){a=5;cout<<"base2="<<a<<endl;}

    base2(int d){a=d;cout<<"base2="<<a<<endl;}
};
class derived:public base1,public base2{
public:
    derived(int h):base1(h){cout<<"derived a ="<<a<<endl; }
};

比如在本例中,最派生類建構函式沒有列出base()的建構函式,所以系統就呼叫了第一個base2()建構函式。但是,預設建構函式雖然名字上叫預設建構函式,但如果你把第一個 base2(){a=5;cout<<"base2="<<a<<endl;} 刪除了,系統是會報錯的!

3.從虛基類直接或間接繼承的派生類中的建構函式的成員初始化列表中都要列出對虛基類建構函式的呼叫。(這裡尤其關注這個間接,就算是從虛基類派生的類中繼承來的類,在寫建構函式時也要列出虛基類)

  1. 最派生類的建構函式在開頭已經呼叫了虛基類的建構函式,之後呼叫的其他基類的建構函式時就不會再呼叫這個虛基類的構造函數了。
  2. C++規定,在一個初始化列表中出現對虛基類和非虛基類的呼叫,則虛基類永遠優於非虛基類的建構函式的執行。

最後兩個小知識:

(1)關鍵字virtual與繼承方式關鍵字(public或private)的先後順序無關緊要,它只說明是“虛擬繼承”。下面二個虛繼承方法是等價

class  derived:virtual public base{
    //…
};
class  derived:public virtual base{
    //…
};

(2). 是一個基類在作為某些派生類虛基類的同時,又作為另一些派生類的非虛基類,這種情況允許的。下例說明了這個問題。

class  B {
    //…
};
class X:virtual  public B {
    //…
};
class Y:virtual  public B {
    //…
};
class Z:public B {
    //…
};
class AA:public X,public Y,public Z {
    //…
};

整理自浙大課程PPT,部分理解為原創