C++筆記------類的繼承和多態

從已有的類派生出新的類,叫繼承。派生類繼承了基類的特徵和方法。
公有繼承:基類的公有成員成爲派生類的公有成員;基類的私有成員成爲派生類的一部分,但只能經過基類成員方法和保護方法訪問。
派生類構造函數,經過成員初始化列表的方式指明使用的基類構造函數,並傳遞基類信息。非構造函數不能使用初始化列表語法。數組

派生類可使用基類不是私有的方法。函數

class A { private: int num; public: int a; public: A():a(10),num(1) {} void Show_num() { cout << num <<endl; } ~A(){} }; class B:public A { public: int b; B():A(),b(5){} ~B(){} }; int main() { B b1; cout << b1.b <<" " << b1.a <<endl; b1.Show_num(); //b1只能經過基類公有方法訪問私有數據。 }

在派生類的對象建立中,首先是虛基類的構造函數,並按照聲明順序構造。而後是非虛基類的構造函數,
以後是成員對象的構造函數,最後是派生類本身的構造函數。
派生類對象過時先調用派生類析構函數,而後再調用基類析構函數。spa

class D1 { public: D1() { cout << "D1 create" <<endl; } ~D1() { cout <<  "D1 free \n"; } }; class D2 { public: D2() { cout << "D2 create" <<endl; } ~D2() { cout <<  "D2 free \n"; } }; class D3 { public: D3() { cout << "D3 create" <<endl; } ~D3() { cout <<  "D3 free \n"; } }; class D4:public D1,virtual public D2 { public: D3 tt; D4():tt() { cout << "D4 create" <<endl; } ~D4() { cout <<  "D4 free \n"; } }; int main() { D4 tt; return 0; }

1.子類能給父類賦值(向上轉換),但父類不能夠給子類賦值指針

2.基類的指針能夠指向派生類,基類的引用能夠引用派生類對象。但只能調用基類的方法。派生類指針和引用不能夠指向基類和引用基類。從新定義基類方法將隱藏基類方法。code

派生類可使用做用域解析符來調用基類方法。對象

class D1 { public: D1() { cout << "D1 create" <<endl; } void show() { cout << "D1 show"<< endl; }

      void show1()
      {
          cout <<" D1 show1()\n";
      }blog

      ~D1()繼承

 { cout <<  "D1 free \n"; } }; class D2 { public: D2() { cout << "D2 create" <<endl; } void show() { cout << "D2 show" <<endl; } ~D2() { cout <<  "D2 free \n"; } }; class D4:public D1,virtual public D2 { public: D4():tt() { cout << "D4 create" <<endl; } void show() { cout << "D4 show" <<endl; }

      void show1(int i)
     {
          cout << i <<" D4 show1()\n";
     }作用域

~D4() { cout <<  "D4 free \n"; } }; int main() { D4 tt; D2 t2; D1 t1; t1 = tt; //tt = t1; //報錯 
    D2* t3 = &tt; D1 & t4=tt; t3->show();      //調用D2的show函數
    t4.show();        //調用D1的show函數
    tt.show();        //調用D1的show函數
    tt.D1::show();  //調用D1的show函數
    //tt.show1();   //報錯,顯示沒有show1()函數
tt.show1(2);
return 0; }

有兩種多態性
  1.編譯時的多態性,經過函數重載和運算符重載實現。
  2.運行時的多態,程序執行時沒法根據函數名和參數肯定調用那一個函數,必須根據具體執行狀況動態的肯定,經過類繼承關係和虛函數實現。
Ps:原型

1.函數若是爲虛函數則在繼承體系中,函數一直默認爲虛函數。

2.派生類中從新定義虛函數時(覆蓋),要函數名,參數列表和返回值要與基類相同(三同)

3.若是返回類型是基類指針,派生類返回派生類指針是能夠的。若是不一樣則重載。

4.靜態成員函數(全部對象共同擁有),內聯函數,全局函數(只有類的成員函數才能是虛函數),不能做爲虛函數。

5.構造函數不能定義爲虛函數,由於調用構造函數是對象沒有完成實例化。

6.若是函數在類內聲明,類外實現。vistual只用在類聲明的方法原型中。

7.使用virtual,程序根據引用或指針的對象選擇方法。沒有virtual,則根據引用或指針類型調用方法。

8.將基類的析構函數定義爲虛析構函數,爲了保護讓程序正確調用析構函數。

9.編譯器處理虛函數是爲對象添加一個隱藏成員,該成員保存了指向虛函數的地址數組的指針,稱爲虛函數表。

重載,隱藏和覆蓋

  重載:在同一做用域中,同名,不一樣參數列表的函數之間是重載。
  隱藏:在父類中的函數沒用virtual關鍵字,子類同名函數會隱藏父類函數,不能使用父類函數
  覆蓋:在虛函數表中,子類的虛函數地址覆蓋父類同名的虛函數地址

在多繼承中虛函數表
  沒有覆蓋的狀況下,子類的虛函數地址只會添加在第一個父類虛函數表後面,其它父類虛函數表中沒有
  在有覆蓋的狀況下,子類的虛函數地址會覆蓋全部父類同名的虛函數地址。

private與protected區別
  派生類成員能夠直接訪問基類保護成員,但不能直接訪問基類私有成員。
  保護訪問控制讓派生類可以訪問公衆不能使用的內部函數。
純虛函數

  virtual void show() = 0 ;

抽象基類(ABC):包含純虛函數的類(不管有無實現),不能建立對象。

  由於純虛函數沒有實現部分,因此不能產生對象。

  子類若是沒有重寫ABC的純虛函數則也不能建立對象,必須把全部純虛函數重寫。

  若是純虛函數提供實現代碼,能夠經過類名作限定進行調用ABC的函數實現代碼。

//有一個抽象基類A(已提供實現代碼)
B b; b.show(); b.A::show();
相關文章
相關標籤/搜索