程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++之鑽石問題和解決方案(菱形繼承問題)

C++之鑽石問題和解決方案(菱形繼承問題)

編輯:C++入門知識

在C++中,什麼叫做鑽石問題(也可以叫菱形繼承問題),怎麼避免它?   下面的圖表可以用來解釋鑽石問題。           假設我們有類B和類C,它們都繼承了相同的類A。另外我們還有類D,類D通過多重繼承機制繼承了類B和類C。因為上述圖表的形狀類似於鑽石(或者菱形),因此這個問題被形象地稱為鑽石問題(菱形繼承問題)。現在,我們將上面的圖表翻譯成具體的代碼:   [cpp]   /*  Animal類對應於圖表的類A  */                                      class Animal { /* ... */ }; // 基類   {   int weight;      public:      int getWeight() { return weight;};      };      class Tiger : public Animal { /* ... */ };      class Lion : public Animal { /* ... */ }                                  class Liger : public Tiger, public Lion { /* ... */ };       在上面的代碼中,我們給出了一個具體的鑽石問題例子。Animal類對應於最頂層類(圖表中的A),Tiger和Lion分別對應於圖表的B和C,Liger類(獅虎獸,即老虎和獅子的雜交種)對應於D。 現在,問題是如果我們有這種繼承結構會出現什麼樣的問題。 看看下面的代碼後再來回答問題吧。 [cpp]   int main( )   {   Liger lg ;      /*編譯錯誤,下面的代碼不會被任何C++編譯器通過 */      int weight = lg.getWeight();     }     在我們的繼承結構中,我們可以看出Tiger和Lion類都繼承自Animal基類。所以問題是:因為Liger多重繼承了Tiger和Lion類,因此Liger類會有兩份Animal類的成員(數據和方法),Liger對象"lg"會包含Animal基類的兩個子對象。 所以,你會問Liger對象有兩個Animal基類的子對象會出現什麼問題?再看看上面的代碼-調用"lg.getWeight()"將會導致一個編譯錯誤。這是因為編譯器並不知道是調用Tiger類的getWeight()還是調用Lion類的getWeight()。所以,調用getWeight方法是不明確的,因此不能通過編譯。   鑽石問題的解決方案:   我們給出了鑽石問題的解釋,但是現在我們要給出一個鑽石問題的解決方案。如果Lion類和Tiger類在分別繼承Animal類時都用virtual來標注,對於每一個Liger對象,C++會保證只有一個Animal類的子對象會被創建。看看下面的代碼: [cpp]   class Tiger : virtual public Animal { /* ... */ };      class Lion : virtual public Animal { /* ... */ }     你可以看出唯一的變化就是我們在類Tiger和類Lion的聲明中增加了"virtual"關鍵字。現在類Liger對象將會只有一個Animal子對象,下面的代碼編譯正常: [cpp]   int main( )   {   Liger lg ;      /*既然我們已經在Tiger和Lion類的定義中聲明了"virtual"關鍵字,於是下面的代碼編譯OK */      int weight = lg.getWeight();     }     因為Java不支持多繼承,所以不會出現菱形繼承問題。但是Java可以通過接口間接實現多重繼承。 [java]   Class Mule implements Horse,Donkey   {       /* Horse和Donkey是接口*/   }    

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved