天天看點

C++基礎——繼承和派生

繼承和派生

屬于父子關系,站在兒子的角度是繼承,站在父親的角度是派生

  1. 為什麼要引入繼承和派生

    解決軟體重用性問題(C語言問題就是在一個項目中寫好拿到另一個項目中不能用),實作了代碼的重用性

  2. 怎麼使用?
    • 文法:class 派生類名:[繼承方式] 基類名

    ​ {

    ​ 派生類成員聲明

    ​ };

    ​ 子類繼承父類會全盤接收,除了構造器和析構器,基類就可能會造成派生類的備援,這是面對對象無法克服的,需要去設計一個好的基類

    • 初始化

      構造、析構、拷貝構造、指派運算符重載以什麼形式到子類中呢?

      • 構造:類内的子對象要麼顯示的初始化(通過傳參調用其構造函數),要麼不顯示初始化自動調用無參的構造器,如果既不顯示也沒有無參構造器的話會報錯。進而推得:子類的初始化中不一定要調用父類的構造器,要麼顯示調用構造器傳參,要麼父類有無參構造器或是預設參數的函數可以包含(無參構造器)。

        子類繼承了父類的私有成員(可以通過sizeof檢視類的大小),隻是無法直接通路,是以需要通過父類的構造函數初始化,調用父類的接口函數使用

      • 析構:析構順序(子類->成員->基類)
      • 拷貝構造:如果都是淺拷貝則不用重新寫,如果是深拷貝需要在重新寫,其中派生類中的預設拷貝構造器會調用父類中預設或者自實作的拷貝構造器,若派生類實作拷貝構造器,則必須顯示的調用父類的拷貝構造器。
      • 指派運算符重載:派生類的預設指派運算符重載函數,會調用父類的指派運算符重載函數(預設或自實作),若派生類自實作指派運算符重載函數,不在發生預設調用,需要手動顯示調用(不調用也不報錯,但是有問題的)
    • 繼承方式 (用public就完事了)
      • 通路方式 public private protected ,在通路方式上protected同private
      • 在public下,父類的public在子類可以通路,并且外面可以通路;父類的protected在子類可以通路,但外面不可通路,privated子類中不可通路,外面更不可通路
      • 繼承方式影響了基類中成員在子類中的通路方式 ,父類是有條件的繼承給子類
      • pri的内容雖然不能繼承,但可以通過函數在public中傳回pri的内容,然後間接被繼承
      • 通路方式 \ 繼承方式 public(99%) protected private
        public public protected private
        protected protected protected private
        private inaccess inaccess inaccess
      • 多級派生
        public 傳承接口 傳承資料
        public public public
        pub 接口 pub pub pub
        pro 接口/資料 pro pro pro
        pri 資料
        protected 傳承資料
        protected protected protected
        pub 接口 pro pro pro
        pro 接口/資料 pro pro pro
        pri 資料
        private 封殺了接口和資料
        private private private
        pub 接口 pri
        pro 接口/資料 pri
        pri 資料
    多級派生中:public相容了資料的隐蔽性(外面無法通路)、接口傳承、資料傳遞,protected隻兼顧了資料的隐蔽性和資料傳遞,private隻兼顧了資料的隐蔽性
  • 既然都用public如此為什麼還要用protected和private?防止基類公用接口的擴散,例如有一些類庫公司不想讓别人看到内部是怎麼做的。
  1. 多繼承
    • 文法
    • 多繼承可以繼承好幾個爹,但也有問題:多個父類中有同名的成員,被繼承到子類中會給通路帶來不友善,浪費空間

      c++提供虛基類和虛繼承機制,實作在多繼承中隻保留一份共同成員,解決多繼承當中同名成員被繼承後引起的通路混亂

      1. 虛基類:提取公因式 M類,是設計和抽象的結果
      2. 虛繼承 virtual:一種繼承的擴充 解決了避免從多個父類中繼承同名的成員

        文法 class 派生類名:virtual 繼承方式 基類名

    • 多繼承會造成三角問題,就存在不同父類重名問題,為了解決将三角問題變成鑽石/四角問題,抽象出M類,形成了爺(基類)父(中間類)孫(派生類),但打破了隔輩不管的原則,在初始化中孫子開始管爺爺了,中間類不受virtual的影響,像普通類一樣使用,virtual的發生階段在生産孫子類的時候生效。

繼續閱讀