C++ 多態

    這篇文章對多態做一個總結,同時對虛函數、純虛函數、重載、覆蓋、隱藏作相應的總結。

1.1 定義

    如果有幾個相似而不完全相同的對象,有時人們要求在向他們發出同一消息時,他們的反應各不相同,分別執行不同的操作,這種情況就是多態現象。C++所謂的多態是指,由繼承而產生的相關的不同的類,其對象對同一消息會作出不同的響應。在基類的函數前加上virtual關鍵字,在派生類中重寫該函數,運行時將會根據對象的實際類型來調用相應的函數。如果對象類型是派生類,就調用派生類的函數;如果對象類型是基類,就調用基類的函數。

2 虛函數

2.1 定義

    虛函數是一種在基類定義爲virtual的函數,並在一個或多個派生類中重新定義的函數。

2.2 格式

class 類名{
    vitrual 函數聲明
};

2.3 規則

  • 在基類中用virtual聲明成員函數爲虛函數。類外實現虛函數時,不必再加virtual;
  • 在派生類中重新定義此函數稱爲覆寫,要求函數名,返回類型,函數參數個數及類型全部匹配。並根據派生類的需要重新定義函數體;
  • 當一個成員函數被聲明爲虛函數後,其派生類中完全相同的函數(顯示的寫出)也爲虛函數。可以在其前面加上vitrual以示清晰;
  • 定義一個基類對象的指針,並使其指向子類的對象,通過該指針調用虛函數,此時調用的就是指針變量指向對象的同名函數;
  • 子類中覆寫的函數,可以爲任意訪問類型,依子類需求決定;
  • 只有類中的成員函數才能聲明爲虛函數,因爲虛函數僅適用於與有繼承關係的類對象,所以普通函數(包括友元函數)不能聲明爲虛函數;
  • 靜態成員函數不能是虛函數,因爲靜態成員函數不受限於某個對象;
  • 內聯函數不能是虛函數,因爲內聯函數不能再運行中動態確定位置;
  • 構造函數不能是虛函數,析構函數可以是虛函數,而且通常聲明爲虛函數(析構函數比較特殊,因爲派生類的析構函數跟基類的析構函數名稱不一樣,但是構成覆蓋,這裏編譯器做了特殊處理);

有關虛函數表的介紹:虛函數表

3 純虛函數

3.1 格式

class 類名{
    vitrual 函數聲明=0;
};

3.2 規則

  • 含有純虛函數的類,稱爲抽象基類,不可實例化。即不能創建對象,存在的意義就是被繼承,提供族類的公共接口,java中稱爲interface。
  • 純虛函數只有聲明,沒有實現,被“初始化”爲0。
  • 如果一個類中聲明瞭純虛函數,而在派生類中沒有對該函數定義,則該虛函數在派生類中仍然爲純虛函數,派生類仍然爲純虛基類。

4 多態

多態可以分爲靜多態和動多態,如下圖所示。

                                         

                                                              圖 1 多態

4.1 靜多態

    靜多態是在編譯的時候就確定調用函數的類型,函數重載就是一個典型的靜多態。

    函數重載的規則:(1)函數名相同;(2)參數的個數不同、參數的類型不同、參數的順序不同,均可構成重載;(3)返回類型不同不可以構成重載;(4)相同的範圍(在同一個類中)。

4.2 動多態

    在運行的時候才確定調用哪個函數,動態綁定。實質是子類重新定義了父類的虛函數,父類的指針根據賦給它的不同子類的指針,動態的調用屬於子類的該函數,這樣的函數調用在編譯期間無法確定。這裏需要引入一個概念:覆蓋。覆蓋是指派生類中重新定義父類中的函數,其函數名、參數列表、返回類型必須同父類中的相對應被覆蓋的函數嚴格一致,只有函數體不同。

覆蓋的規則:(1)函數名相同;(2)參數相同;(3)基類函數必須有virtual關鍵字;

上面已經提及重載和覆蓋,接着說一下隱藏:隱藏是指派生類的函數屏蔽了與其同名的基類函數。

規則:(1)如果派生類的函數與基類的函數同名,但是參數不同,此時,不論有無virtual關鍵字,基類的函數將被隱藏(注意別與重載混淆);(2)如果派生類的函數與基類的函數同名,並且參數也相同,但是基類函數沒有virtual關鍵字。此時,基類的函數被隱藏(注意別與覆蓋混淆);

加個圖:


                                                         圖2 重載、覆蓋和重定義的區別

Reference :





發佈了274 篇原創文章 · 獲贊 50 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章