C++的三大特性封裝、繼承和多態

 

封裝可使得代碼模塊化,繼承能夠擴展已存在的代碼,他們的目的都是爲了代碼重用。而多態的目的則是爲了接口重用ios

  • 封裝:封裝是在設計類的一個基本原理,是將抽象獲得的數據和行爲(或功能)相結合,造成一個有機的總體,也就是將數據與對數據進行的操做進行有機的結合,造成「類」,其中數據和函數都是類的成員。c++

  • 繼承:若是一個類別B「繼承自」另外一個類別A,就把這個B稱爲「A的子類」,而把A稱爲「B的父類別」也能夠稱「A是B的超類」。繼承可使得子類具備父類別的各類屬性和方法,而不須要再次編寫相同的代碼。在令子類別繼承父類別的同時,能夠從新定義某些屬性,並重寫某些方法,即覆蓋父類別的原有屬性和方法,使其得到與父類別不一樣的功能。編程

    1. 訪問權限模塊化

      • public: 父類對象內部、父類對象外部、子類對象內部、子類對象外部均可以訪問。
      • protected:父類對象內部、子類對象內部能夠訪問,父類對象外部、子類對象外部都不可訪問。
      • private:父類對象內部能夠訪問,其餘都不能夠訪問。

      |訪問對象|public|protected|private|
      |-|-|-|-|
      |父類|可見|可見|可見|
      |子類|可見|可見|不可見|
      |父類外部|可見|不可見|不可見|
      |子類外部|可見|不可見|不可見|函數

    2. 繼承方式
      ps.三種繼承方式不影響子類對父類的訪問權限,子類對父類只看父類的訪問控制權。繼承方式是爲了控制子類(也稱派生類)的調用方(也叫用戶)對父類(也稱基類)的訪問權限。public、protected、private三種繼承方式,至關於把父類的public訪問權限在子類中變成了對應的權限。 如protected繼承,把父類中的public成員在本類中變成了protected的訪問控制權限;private繼承,把父類的public成員和protected成員在本類中變成了private訪問控制權。優化

      ps.友元是類級別的,不存在繼承的問題。設計

  • 多態:多態性能夠簡單地歸納爲「一個接口,多種方法」,程序在運行時才決定調用的函數,它是面向對象編程領域的核心概念。多態(polymorphism),字面意思多種形狀。指針

    1. 靜態多態:靜態多態也稱爲靜態綁定或早綁定。編譯器在編譯期間完成的,編譯器根據函數實參的類型(可能會進行隱式類型轉換),可推斷出要調用那個函數,若是有對應的函數就調用該函數,不然出現編譯錯誤。調試

      • 函數重載code

        編譯器根據函數不一樣的參數表,對同名函數的名稱作修飾,而後這些同名函數就成了不一樣的函數(至少對於編譯器來講是這樣的)。函數的調用,在編譯器間就已經肯定了,是靜態的。也就是說,它們的地址在編譯期就綁定了(早綁定)。

      • 泛型編程

        泛型編程就是指編寫獨立於特定類型的代碼,泛型在C++中的主要實現爲模板函數和模板類。
        泛型的特性:

        1. 函數模板並非真正的函數,它只是C++編譯生成具體函數的一個模子。
          1. 函數模板自己並不生成函數,實際生成的函數是替換函數模板的那個函數,好比上例中的add(sum1,sum2),這種替換是編譯期就綁定的。
          3. 函數模板不是隻編譯一份知足多重須要,而是爲每一種替換它的函數編譯一份。
          4. 函數模板不容許自動類型轉換。
          5. 函數模板不能夠設置默認模板實參。好比template <typename T=0>不能夠。
    2. 動態多態
      c++的動態多態是基於虛函數的。對於相關的對象類型,肯定它們之間的一個共同功能集,而後在基類中,把這些共同的功能聲明爲多個公共的虛函數接口。各個子類重寫這些虛函數,以完成具體的功能。客戶端的代碼(操做函數)經過指向基類的引用或指針來操做這些對象,對虛函數的調用會自動綁定到實際提供的子類對象上去。

    3. 宏多態(?)
      帶變量的宏能夠實現一種初級形式的靜態多態:

      #include <iostream>
      #include <string>
      
      // 定義泛化記號:宏ADD
      #define ADD(A, B) (A) + (B);
      
      int main()
      {
          int i1(1), i2(2);
          std::string s1("Hello, "), s2("world!");
          int i = ADD(i1, i2);                        // 兩個整數相加
          std::string s = ADD(s1, s2);                // 兩個字符串「相加」
          std::cout << "i = " << i << "/n";
          std::cout << "s = " << s << "/n";
      }
    4. 動態多態和靜態多態的比較

      1. 靜態多態
        • 優勢:
          1. 因爲靜多態是在編譯期完成的,所以效率較高,編譯器也能夠進行優化;
          2. 有很強的適配性和鬆耦合性,好比能夠經過偏特化、全特化來處理特殊類型;
          3. 最重要一點是靜態多態經過模板編程爲C++帶來了泛型設計的概念,好比強大的STL庫。
        • 缺點:
          1. 因爲是模板來實現靜態多態,所以模板的不足也就是靜多態的劣勢,好比調試困難、編譯耗時、代碼膨脹、編譯器支持的兼容性不可以處理異質對象集合
      2. 動態多態
        • 優勢:
          1. OO設計,對是客觀世界的直覺認識;
          2. 實現與接口分離,可複用
          3. 處理同一繼承體系下異質對象集合的強大威力
        • 缺點:
          1. 運行期綁定,致使必定程度的運行時開銷;
          2. 編譯器沒法對虛函數進行優化
          3. 笨重的類繼承體系,對接口的修改影響整個類層次;
      3. 不一樣點:
        • 本質不一樣,遲早綁定。靜態多態在編譯期決定,由模板具現完成,而動態多態在運行期決定,由繼承、虛函數實現;
        • 動態多態中接口是顯式的,以函數簽名爲中心,多態經過虛函數在運行期實現,靜態多臺中接口是隱式的,以有效表達式爲中心,多態經過模板具如今編譯期完成
      4. 相同點:
        • 都可以實現多態性,靜態多態/編譯期多態、動態多態/運行期多態;
        • 都可以使接口和實現相分離,一個是模板定義接口,類型參數定義實現,一個是基類虛函數定義接口,繼承類負責實現;
相關文章
相關標籤/搜索