虛基類


1.虛基類的概念
    
          在C++語言中,一個類不能被多次說明為一個派生類的直接基類,但可以不止一次地成為間接基類。這就導致了一些問題。為了方便 說明,先介紹多繼承的“類格”表示法。
       
          派生類及其基類可用一有向無環圖(DAG)表示,其中的箭頭表示“由派生而來”。類的DAG常稱為一個“類格”。復雜類格畫出來通常更容易理解。例如:

5-19
class L
{ public:
int next;

};
class A : public L
{ };
class B : public L
{ };
class C : public A, public B
{ public :
void f()
{
next=0;
}
};


這時,next有兩個賦值語句next=0; 具有二義性,它是將A::next置為零,還是將B::next置為零,或者將兩者都置為0,需要在函數f()中被顯式的說明.
如果希望間接基類L與其派生類的關系是如下圖

 

當在多條繼承路徑上有一個公共的基類,在這些路徑中的某幾條路經匯合處,這個公共基類就會產生多個實例。

         如果只想保存這個基類的一個實例,可以將這個公共基類說明為虛擬基類或稱虛基類。
         
       它僅是簡單地將關鍵字virtual加到基類的描述上,例如改寫上述例子為例5-20


注意!!!

 

一個派生類的對象的地址可以直接賦給虛基類的指針,例如:
             C  obj;
              L  * ptr=&obj;
    這時不需要強制類型轉換,並且,一個虛基類的引用可以引用一個派生類的對象,例如:  
         C  obj2;
          L &ref=obj2;
       反之則不行,無論在強制類型轉換中指定什么路徑,一個虛基類的指針或引用不能轉換為派生類的指針或引用。例如:
        C  * P=(C*)(A*)ptr;
 將產生編譯錯誤。

 

 

2. 虛基類對象的初始化
        虛基類的初始化與多繼承的初始化在語法上是一樣的,但隱含的構造函數的調用次序有點差別。
        虛基類構造函數的調用次序是這樣規定的:
        1. 虛基類的構造函數在非虛基類之前調用。
        2. 若同一層次中包含多個虛基類,虛基類構造函數按它們說明的次序調用。
        3. 若虛基類由非虛基類派生,則遵守先調用基類構造函數,再調用派生類構造函數的規則。

 

例如 :
           class  X :  public Y, virtual public Z
               {     }
                   X one;
         將產生如下調用次序:
                  Z()
                  Y()
                  X()
         這里Z是X的虛基類,故先調用Z的構造函數,再調用Y的構造函數,最后才調用派生類X自己的構造函數。



 

# include "iostream.h"       
class base
{
public:
base()
{cout<<"Base"<<endl;}
};
class base2
{
public:
base2()
{cout<<"Base2"<<endl;}
};

class level1 : public base2, virtual public base
{
public:
level1()
{cout<<"level1"<<endl;}
};
class level2 : public base2, virtual public base
{
public:
level2()
{cout<<"level2"<<endl;}
};
class toplevel : public level1, virtual public level2
{
public:
toplevel()
{cout<<"toplevel"<<endl;}
};

當建立對象view時,將產生如下調用次序:
            level2()
            level1()
            toplevel()
     而level2()要求:
       base()
        base2()
        level2()
        level1()要求
         base2()
         level1()
        toplevel()要求
         toplevel()

 

 

所以,構造函數的調用順序為:
             base()
             base2()
             level2()        
          base2()
             level1()
             toplevel()


 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM