c++基礎10:繼承和派生 虛函數的作用 多態性概念 純虛函數和抽象類的概念

一.繼承和派生

1.概念:

基類(父類):原有的類

派生類(子類):基於基類新建立的類

派生(類的派生):在原有類的基礎上建立新類並且添加新特徵的過程

繼承:子類不加修改延續父類的特徵

 

2.單一繼承:子類只有一個基類的繼承

多重繼承:子類擁有多個基類的繼承叫多重繼承

 

3.使用冒號(:)來聲明派生類(子類):

class 子類:public 父類

 

上面的聲明表示冒號前面的類(子類)是從冒號後面的類(父類)派生來的,注意父類前面必須使用public來修飾,否則子類對象不能賦值給父類的對象

 

4.protect修飾符

protect:只有自身和子類才能訪問,其他類不能訪問

private:只有自身才能訪問,其他類不能訪問

public:所有都能訪問

 

5.子類和父類之間的賦值

class father

{}

class son:public father

{}

father a;

son b;

a=b;//可以

b=a;//不行

注意:父類對象不能賦值給子類的對象,這是因爲父類的對象成員比子類的對象成員少(子類會增加一些新功能),如果使用子類對象訪問父類的成員,可能出現找不到成員的現象,導致程序出錯。

 

6.定義子類構造函數

6.1 定義形式:

子類:子類構造函數(參數):父類1(參數),父類2(參數)。。。

6.2 構造函數的執行順序:首先調用基類的構造函數,在執行子類的構造函數;釋放對象時,先調用子類的析構函數,再調用父類的析構函數

 

7.解決程序的兩義性問題:

class A

{

   public:

      void hello(){cout<<"我是父類A"<<endl;}

}

class B

{

   public:

      void hello(){cout<<"我是父類B"<<endl;}
}

class C:public A,public B

{

   public:

     void hello(){cout<<"我是子類C"<<endl;}

}
void main()
{
   C c;
   c.hello();//輸出“我是子類C”
}

在main函數中調用hello函數,會執行子類C的hello函數,但是如果我想輸出父類A的hello函數,那麼就應該使用

作用域操作符(::) 用它來指定函數屬於那個類:

c.A::hello();

這樣就能輸出“我是父類A”

二.虛函數

如果使用父類的指針來訪問子類的對象成員,那麼他能執行到子類的成員嗎?看下面的例子:

class falther

{

public:

  void run()

  {

    cout<<"父親可以跑萬米!"<<endl;

  }

}

class son:public falther

{

public:

  void run()

  {

    cout<<"兒子可以跑一百萬米!"<<endl;

  }

}

void main()

{

   falther *fa=new son();

   fa->run();//輸出“父親可以跑萬米”

  delete fa;

}

沒錯,使用父指針fa不能訪問子對象的函數run,那麼怎麼才能輸出“兒子可以跑一百萬米”呢?

解決辦法:在父類的函數run前面加上關鍵字virtual,也就是父類是虛函數,然後使用系統執行到關鍵字virtual函數的時候,就會自動判斷哪個對象調用了它,然後調用該對象的同名函數,修改程序如下:

class falther

{

public:

  virtual void run()

  {

    cout<<"父親可以跑萬米!"<<endl;

  }

}

class son:public falther

{

public:

  void run()

  {

    cout<<"兒子可以跑一百萬米!"<<endl;

  }

}

void main()

{

   falther *fa=new son();

   fa->run();//輸出“兒子可以跑一百萬米”

  delete fa;

}

上面使用父指針就可以輸出了“兒子可以跑一百萬米”

 三.多態性(c++三大特性:封裝性,繼承性,多態性)

以上面的father和son的例子解釋多態性:

      當c++編譯器在編譯的時候,發現father類的run()函數是虛函數,這個時候c++就會採用遲綁定(late binding)技術。也就是編譯時不確定具體調用的函數,而是在運行時,根據對象的類型(在程序中,我們傳遞的是son類對象的地址)來確認是哪個函數,這種能力就叫做c++的多態性。我們如果沒有在father類的run()前加上vitual關鍵字,c++編譯器在編譯時就確定了哪個函數被調用(調用father中的run),這叫做早期綁定(early binding)。

     c++多態性概念:在基類的函數前加上virtual關鍵字,在派生類中重寫該函數,運行時就會根據對象的實際類型調用相應的函數。也就是說如果對象類型是派生類,就調用派生類的函數;如果對象類型是基類,就調用基類的函數。

    注意:c++的多態性只能通過虛函數來體現。

 

四.純虛函數和抽象類

class falther{public: virtual void run()=0;}

上面在father類中的虛函數run的函數體=0,這種定義方式就定義一個純虛函數run。

純虛函數是指被標明爲不具體實現的虛函數,它讓類先有一個操作名稱,而沒有操作內容,讓派生類在繼承的時候去具體的實現。凡是含有純虛函數的類就叫做抽象類。抽象類是不能聲明一個對象的,只能作爲基類爲派生類服務。因爲抽象類聲明一個對象,調用其函數是沒有意義的。注意:如果派生類也沒具體的實現抽象類中的純虛函數,那麼派生類也會變成一個抽象類,不能實例化對象。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章