1. 程式人生 > >C++_代碼重用4-多重繼承

C++_代碼重用4-多重繼承

span 如何解決 兩個 存在 初始化 這樣的 RKE 否則 所有

繼承使用時要註意,默認是私有派生。所以要公有派生時必須記得加關鍵字Public。

MI(Multi Inheritance)會帶來哪些問題?以及如何解決它們?

兩個主要問題:

從兩個不同的基類繼承同名方法;

從兩個或更多相關基類那裏繼承同一個類的多個實例;

虛方法

Worker公有派生出Singer和Waiter;

然後Singer和Waiter公有派生出SingingWaiter(即多重繼承);

這樣會導致一個問題,就是SingingWaiter中有兩個Worker組件。通常可以將派生類對象的地址賦值給基類指針。但是在這樣的情況下這麽做的話,將出現二義性。所以必須使用類型轉換來指定對象。但這又增加了指針引用的復雜度。

C++在引入多重繼承的同時,也引入新技術——虛基類,來解決該問題。

虛基類也用關鍵字virtual,虛基類與虛函數之間並不存在明顯的聯系。這麽做是為了給程序員減少壓力,類似於關鍵字的重載。

class Singer: virtual public Worker{…};

class Waiter: public virtual Worker{…};

(virtual和public的次序無關緊要)

那麽為什麽不使虛行為成為MI的默認準則呢?

在一些情況下,可能需要基類的多個拷貝;

將基類作為虛的要求程序完成額外的計算,為不需要的程序付出代價是不應當的;

新的構造函數規則

使用虛基類時,必須對構造函數采用新的方法;

對於非虛基類,唯一可以出現在初始化列表中的構造函數是即時基類構造函數。

A派生B,B派生C;--->C類的構造函數只能調用B類的構造函數,B類的構造函數只能調用A類構造函數。

但對於虛基類而言,這種信息自動傳遞方式不可用。這是因為對於多重繼承而言,信息傳遞將通過兩條不同的途徑。為避免這種沖突,當基類是虛的,將禁止信息通過中間類自動傳遞給基類。

這就要求顯式地調用所需的基類構造函數:

SingingWaiter(參數列表):Worker(wk),Waiter(wk,p),Singer(wk,v) { }

上述格式對虛基類來說是合法的,對非虛基類來說是非法的。

哪個方法

對於多重繼承,如果每個祖先都有一個Show函數,那麽會導致函數調用的二義性

對於單繼承,如果沒有重新定義show,將調用最近祖先中的show定義。

有幾種解決方法:

1使用作用域解析運算符來澄清編程者的意圖;

2或是在多重繼承的類中重新定義show方法,並指出要使用哪個show;

這種遞增的方法對於單繼承來說是有效的;

但是對於多重繼承來說,還是有問題:

SingingWaiter::Show

{Singer::Show();Waiter::Show();} //這將顯示姓名和ID兩次。

該如何解決呢?->使用模塊化方法,而不是遞增的方法;即提供一個只顯示worker組件的方法,提供一個只顯示waiter組件及singer組件的方法。

將所有數據組件都設置為保護的方法,而不是私有的,可以更嚴格地控制對數據的訪問;

如果數據組件的方法是保護的,則只能在繼承層次結構中的類中使用它,在其他地方則不能使用。

MI小結

MI會增加編程的復雜度。然而,這種復雜度主要是由於派生類通過多條途徑繼承同一個基類引起的。

當派生類使用關鍵字virtual來指示派生時,基類就稱為了虛基類。其構造函數的規則有所變化,不會自動進行信息不換傳遞,需要顯式地調用基類構造函數。

通過優先規則解決名稱二義性。如果一個類從兩個不同的類那裏繼承了兩個同名的成員,則需要在派生類中使用類限定符來區分它們。否則,編譯器將指出二義性。

有間接虛基類的派生類包含直接調用間接基類構造函數的構造函數,這對於間接非虛基類來說是非法的。

C++_代碼重用4-多重繼承