高效C++:繼承和實現


  如何正確的使用繼承和實現是本章說明的重點。

 

確定public繼承的關系是is-a

  • public繼承等同於is-a

  • 對public繼承,所有base的特性,在derived上都適用

 

避免遮掩繼承而來的名稱

  • Deried中的函數會掩蓋base中的函數,不論函數是成員函數、虛函數亦或是純虛函數(不同作用域的函數,名稱相同也不構成重載)

  • 使用 using base::f 的語法在Deried中強制使用base中被掩蓋的函數

  • 一定要記清楚,Deried中使用base中的同名函數就違背is-a法則

 

區分接口實現和實現繼承

  • non-virtual:指定接口繼承和強制實現

  • virtual:指定接口繼承和一個缺省實現版本

  • pure-virtual分兩種情況:

    • 沒有函實現:指定接口繼承

    • 有函數實現:指定接口繼承和一個缺省實現版本(加作用域調用)------ 和virtual相同

 

考慮virtual以外的實現

  • 虛函數的功能也可以被其他設計方法替代,從而避免虛函數的坑
  • 成員函數中調用虛函數是多態,調用虛函數時可以理解為this->f(),且此時沒有public、protect和private的顯示,因為是類內調用

    • non-virtual-interface

    • Dase中調用virtual函數,Deried中重寫virtual函數,調用實際由Base確定,實現由Deried確認

  • Function Pointer

    • 函數指針作為類的成員變量,另外提供接口調用函數指針指向的函數

  • 使用模板函數對象代替函數指針

  • 將不同功能的函數設計在兩個類中,實現成兩種不同的繼承體系

 

絕不重新定義繼承而來的non-virtual函數

  • 注意繼承中的名稱遮掩(遮掩是對類外調用而言,不要和權限混淆,都當成public考慮)

 

絕不重新定義繼承而來的缺省參數

  • 在不覆蓋non-virtual函數的前提下,絕不重新定義繼承而來的缺省參數只針對virtual而言

  • 函數參數的缺省值是靜態綁定的,virtual是動態綁定的,所以不要重新定義參數的默認值

  • 可以使用NVI方式解決,no-virtual函數調用virtual函數,因為no-virtual函數絕對不能被掩蓋,也就不會修改默認值

 

通過復合建模has-a或根據某物實現

  • A類中有B類的對象,叫has-a

  • 復合比繼承擴張性更好

 

謹慎的使用private繼承

  • private繼承意味着has-a,和復合的概念相同

  • 能用復合就不用private,除非是特殊情況,Deried要繼承Base中的protect成員

  • private繼承可以節約內存

 

明智和謹慎的使用多重繼承

  • 多重繼承比較復雜,且容易導致二義性

  • virtual繼承會增加復雜度等成本

  • 多重繼承的使用場景:實現多個接口,繼承一個基類

  • 建議:不使用多繼承,使用單繼承和實現多接口

 


免責聲明!

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



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