C++中的多重繼承

來源:互聯網
上載者:User
C++中的多重繼承

雖然在軟體設計中,許多書籍都推薦優先使用組合而不是繼承,然而繼承仍然擁有許多天然的優勢,對基類成員的自動擁有,而不用像組合要顯示地去轉向調用所需複用的成員,從而平添更多的代碼。

多重繼承在某些情況下,可以使我們的設計具有更多的靈活性,下面我們討論一些多重繼承中的問題及解決辦法。

 

我們實現了一個抽象基類A,然後由此派生了出了諸多的實作類別,如A1,A2,A3,在項目的起初,這些A的具體類工作很好,我們的軟體模組也依賴於這一個抽象基類A。一切都很好。隨著項目的進行。我們又進入了另一個模組的開發。也許起先的考慮不周,也許設計師在設計時出現了其他什麼,這裡我們又要使用這些A1,A2,A3了。但是我們也發現,抽象基類A的這些介面方法已經不能滿足這一個模組的功能要求了,在這個新的模組中,我們需要另一些通用的方法幹其它的一些事情。怎麼辦?我們要重寫A1,A2,A3,並且加入在新模組中所需要的這些通用的方法嗎?但是根據軟體開發的介面依賴原則,我們的軟體模組還能夠依賴於抽象基類A嗎?可是這些新增的通用方法並未在A中聲明。或許我們應該考慮一下多重繼承,將新增的通用方法抽象到一個新的介面B中。這樣我們在使用A1的新增方法時,只需依賴於這個新的介面B,而在使用A1以前的方法時,只需依賴於介面A。

真是個好主意。於是新的衍生類別實現了。A11繼承於A1和B,A22繼承於A2和B,A33繼承於A3和B,應用環境如下:

 

bool App::AddSub(B* b)

{

       A* a = dynamic_cast<A*>(b);     //動態轉換為A;

 

       If (a!=0)

       a->MethodA();

else

       return false //轉換出錯,輸入參數不是我們期望的類型;

 

b->MethodB(); //調用介面B中的方法;

 

return true;

}

 

可以看到,軟體模組依賴於一個介面B,同時還要驗證其是否繼承自A,否則便不是該模組所需的類型。

該模組可以很好地運行。但注意上面對類型A的轉換是通過動態類型轉換來實現的。而其具體的實現依賴於RTTI,而在某些情況下,我們不能應用RTTI機制。如果我們關掉編譯器的RTTI選項。上面的代碼可能就不能正確運行了。怎麼辦呢?如果我們知道多重繼承的機制,這或許可以協助我們解決這個問題。可以參考C++編程思想或深度探索C++物件模型的相關章節。

下面是一種解決方案。

我們在B中增加一個多態的virtual void* GetThis()方法用以返回this指標,並在A11,A22,A33中都有它的實現,在應用環境中:

 

bool App::AddSub(B* b)

{

       A* a = static_cast<A*>(b->GetThis());             

a->MethodA(); //調用介面A中的方法;

b->MethodB(); //調用介面B中的方法;

 

return true;

}

 

上面的實現中通過多態的GetThis()方法,獲得具體實作類別的指標並轉換為A,但是由於編譯器關閉了對RTTI的支援,這種轉換並非型別安全,需要事先約定傳入類型包括了對A,B的實現,否則轉換將不能達到我們期望的效果。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.