C++類和對象知識點整理七----虛基類和虛繼承

25、C++虛繼承和虛基類
多繼承(Multiple Lnheritance)是指從多個直接基類中產生派生類的能力。多繼承的派生類繼承了所有父類的成員。


儘管概念上非常簡單,但是多個基類的相互交織可能會帶來錯綜複雜的設計問題,命名衝突就是不可迴避的一個。


如:菱形繼承
解決方法 :爲了消除歧義,我們可以在成員變量前面指明它具體來自哪一個類。


b.爲了解決多繼承時的命名衝突和冗餘數據問題,C++提出了虛繼承,使得在派生類中只保留一份間接基類的成員。


在繼承方式前面加上virtual關鍵字就是虛繼承


c.虛繼承目的:是讓某個類做出聲明,承若願意共享它的基類。其中,這個被共享的基類就稱爲虛基類,在這種機制下,不論虛基類在繼承體系中出現了多少次,在派生類中只包含一份虛基類的成員。


虛派生隻影響從指定的虛基類的派生類中進一步派生出來的類,並不會影響派生類本身


C++標準庫中的 iostream 類就是一個虛繼承的實際應用案例。iostream 從 istream 和 ostream 直接繼承而來,而 istream 和 ostream 又都繼承自一個共同的名爲 base_ios 的類,是典型的菱形繼承。此時 istream 和 ostream 必須採用虛繼承,否則將導致 iostream 類中保留兩份 base_ios 類的成員


d.虛基類成員的可見性
因爲在虛繼承的最終派生類中只保留了一份虛基類的成員,所以該成員可以被直接訪問,不會產生二義性。此外,如果虛基類的成員只被一條派生路徑覆蓋,那麼仍然可以直接訪問這個被覆蓋的成員。但是如果該成員被兩條或多條路徑覆蓋了,那就不能直接訪問了,此時必須指明該成員屬於哪個類。


以菱形繼承爲例,假設 A 定義了一個名爲 x 的成員變量,當我們在 D 中直接訪問 x 時,會有三種可能性:
如果 B 和 C 中都沒有 x 的定義,那麼 x 將被解析爲 A 的成員,此時不存在二義性。
如果 B 或 C 其中的一個類定義了 x,也不會有二義性,派生類的 x 比虛基類的 x 優先級更高。
如果 B 和 C 中都定義了 x,那麼直接訪問 x 將產生二義性問題。


可以看到,使用多繼承經常會出現二義性問題,必須十分小心。上面的例子是簡單的,如果繼承的層次再多一些,關係更復雜一些,程序員就很容易陷人迷魂陣,程序的編寫、調試和維護工作都會變得更加困難,因此我不提倡在程序中使用多繼承,只有在比較簡單和不易出現二義性的情況或實在必要時才使用多繼承,能用單一繼承解決的問題就不要使用多繼承。也正是由於這個原因,C++ 之後的很多面向對象的編程語言,例如 Java、C#、PHP 等,都不支持多繼承。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章