C++三大特性之多態

來源:互聯網
上載者:User

標籤:類類型   屏蔽   strong   dep   瞭解   賦值   重新定義   特性   常見   

原文地址:https://qunxinghu.github.io/2016/09/08/C++%20%E4%B8%89%E5%A4%A7%E7%89%B9%E6%80%A7%E4%B9%8B%E5%A4%9A%E6%80%81/

概念多態(Polymorphisn)

多態性是允許你將父物件設定成為和一個或更多的他的子物件相等的技術,賦值之後,父物件就可以根據當前賦值給它的子物件的特性以不同的方式運作。簡單的說:允許將子類類型的指標賦值給父類類型的指標(一個介面,多種方法)。
C++ 支援兩種多態性:編譯時間多態性,運行時多態性。
a、編譯時間多態性(靜態多態):通過重載函數實現
b、運行時多態性(動態多態):通過虛函數實現。

多態的作用

那麼多態的作用是什麼呢,封裝可以使得代碼模組化,繼承可以擴充已存在的代碼,他們的目的都是為了代碼重用。而多態的目的則是為了介面重用。也就是說,不論傳遞過來的究竟是那個類的對象,函數都能夠通過同一個介面調用到適應各自對象的實現方法。

多態的用法

運行時多態:

最常見的用法就是聲明基類的指標,利用該指標指向任意一個子類對象,調用相應的虛函數,可以根據指向的子類的不同而實現不同的方法。如果沒有使用虛函數的話,則利用基類指標調用相應的函數的時候,將總被限制在基類函數本身,而無法調用到子類中被重寫過的函數。因為沒有多態性,函數調用的地址將是一定的,而固定的地址將始終調用到同一個函數,這就無法實現一個介面,多種方法的目的了。

非運行時多態:

通過函數重載實現

簡而言之:

  1. 有virtual才可能發生動態多態現象
  2. (無virtual)調用就按原類型調用
令人迷惑的隱藏規則

隱藏是指衍生類別的函數屏蔽了與其同名的基類函數,規則如下:

  • 如果衍生類別的函數與基類的函數同名,但是參數不同。此時,不論有無virtual關鍵字,基類的函數將被隱藏(注意別與重載混淆,重載是在同一個類中,而隱藏涉及衍生類別與基類)。
  • 如果衍生類別的函數與基類的函數同名,並且參數也相同,但是基類函數沒有virtual關鍵字。此時,基類的函數被隱藏(注意別與覆蓋混淆,覆蓋有virtual關鍵字)。
C++虛函數

虛函數: 就是允許被其子類重新定義的成員函數,子類重新定義父類虛函數的做法,可實現成員函數的動態覆蓋(Override)。

純虛函數: 是在基類中聲明的虛函數,它在基類中沒有定義,但要求任何衍生類別都要定義自己的實現方法。在基類中實現純虛函數的方法是在函數原型後加“=0”

virtual void funtion()=0

抽象類別: 包含純虛函數的類稱為抽象類別。由於抽象類別包含了沒有定義的純虛函數,所以不能進行執行個體化。

純虛函數的作用:

  1. 為了方便使用多態特性,我們常常需要在基類中定義虛擬函數。
  2. 在很多情況下,基類本身產生對象是不合情理的。例如,動物作為一個基類可以派生出老虎、孔雀等子類,但動物本身產生對象明顯不合常理。
    為瞭解決上述問題,引入了純虛函數的概念,將函數定義為純虛函數(方法:virtual ReturnType Function()= 0;),則編譯器要求在衍生類別中必須予以重寫以實現多態性。同時含有純虛擬函數的類稱為抽象類別,它不能產生對象。這樣就很好地解決了上述兩個問題。

範例程式碼:

#include<iostream>using namespace std;//基類對象class Base{public:    //有virtual關鍵字,運行時多態    virtual void f(float x)    {        cout<<"Base::f(float)"<< x <<endl;    }    //無viratul關鍵字,不會發生運行時多態    void g(float x)    {        cout<<"Base::g(float)"<< x <<endl;    }    void h(float x)    {        cout<<"Base::h(float)"<< x <<endl;    }};class Derived : public Base{public:    virtual void f(float x)    {        cout<<"Derived::f(float)"<< x <<endl;   //多態、覆蓋    }    //子類與父類的函數同名,無virtual關鍵字,則為隱藏    void g(int x)    {        cout<<"Derived::g(int)"<< x <<endl;     //隱藏    }    void h(float x)    {        cout<<"Derived::h(float)"<< x <<endl;   //隱藏    }};int main(void){    Derived d;  //子類    Base *pb = &d;  //基類指標指向子類    Derived *pd = &d;   //子類指標指向自己    // Good : behavior depends solely on type of the object    pb->f(3.14f);   // Derived::f(float) 3.14   調用子類,多態    pd->f(3.14f);   // Derived::f(float) 3.14   調用子類    // Bad : behavior depends on type of the pointer    pb->g(3.14f);   // Base::g(float)  3.14 無多態,調用自己的    pd->g(3.14f);   // Derived::g(int) 3    無多態,調用自己的    // Bad : behavior depends on type of the pointer    pb->h(3.14f);   // Base::h(float) 3.14  無多態,調用自己的    pd->h(3.14f);   // Derived::h(float) 3.14   無多態,調用自己的    return 0;}

C++三大特性之多態

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.