欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++中虛函數(shù)與純虛函數(shù)的用法

 更新時間:2014年08月14日 17:15:45   投稿:shichen2014  
這篇文章主要介紹了C++中虛函數(shù)與純虛函數(shù)的用法,是非常重要的概念,需要的朋友可以參考下

本文較為深入的分析了C++中虛函數(shù)與純虛函數(shù)的用法,對于學習和掌握面向?qū)ο蟪绦蛟O計來說是至關重要的。具體內(nèi)容如下:

首先,面向?qū)ο蟪绦蛟O計(object-oriented programming)的核心思想是數(shù)據(jù)抽象、繼承、動態(tài)綁定。通過數(shù)據(jù)抽象,可以使類的接口與實現(xiàn)分離,使用繼承,可以更容易地定義與其他類相似但不完全相同的新類,使用動態(tài)綁定,可以在一定程度上忽略相似類的區(qū)別,而以統(tǒng)一的方式使用它們的對象

虛函數(shù)的作用是實現(xiàn)多態(tài)性(Polymorphism),多態(tài)性是將接口與實現(xiàn)進行分離,采用共同的方法,但因個體差異而采用不同的策略。純虛函數(shù)則是一種特殊的虛函數(shù)。虛函數(shù)聯(lián)系到多態(tài),多態(tài)聯(lián)系到繼承。所以本文中都是在繼承層次上做文章。沒了繼承,什么都沒得談。

一、虛函數(shù)

1 . 定義

在C++中,基類必須將它的兩種成員函數(shù)區(qū)分開來:一種是基類希望其派生類進行覆蓋的函數(shù);另一種是基類希望派生類直接繼承而不要改變的函數(shù)。對于前者,基類通過在函數(shù)之前加上virtual關鍵字將其定義為虛函數(shù)(virtual)。

class Base{ // 基類 
public: 
  virtual int func(int n) const; 
}; 
 
class Derive_Class : public Base{ 
public: 
  int func(int n) const; // 默認也為虛函數(shù) 
}; 

當我們在派生類中覆蓋某個函數(shù)時,可以在函數(shù)前加virtual關鍵字。然而這不是必須的,因為一旦某個函數(shù)被聲明成虛函數(shù),則所有派生類中它都是虛函數(shù)。任何構造函數(shù)之外的非靜態(tài)函數(shù)都可以是虛函數(shù)。派生類經(jīng)常(但不總是)覆蓋它繼承的虛函數(shù),如果派生類沒有覆蓋其基類中某個虛函數(shù),則該虛函數(shù)的行為類似于其他的普通成員,派生類會直接繼承其在基類中的版本。

2 . 動態(tài)綁定

當我們使用基類的引用(或指針)調(diào)用一個虛函數(shù)時將發(fā)生動態(tài)綁定(dynamic binding)。因為我們直到運行時才能知道到底調(diào)用了哪個版本的虛函數(shù),可能是基類中的版本也可能是派生類中的版本,判斷的依據(jù)是引用(或指針)所綁定的對象的真實類型。與非虛函數(shù)在編譯時綁定不同,虛函數(shù)是在運行時選擇函數(shù)的版本,所以動態(tài)綁定也叫運行時綁定(run-time binding)。

3 . 靜態(tài)類型與動態(tài)類型

靜態(tài)類型指的是變量聲明時的類型或表達式生成的類型,它在編譯時總是已知的;動態(tài)類型指的是變量或表達式表示的內(nèi)存中的對象的類型,它直到運行時才可知。當且僅當通過基類的指針或引用調(diào)用虛函數(shù)時,才會在運行時解析該調(diào)用,也只有在這種情況下對象的動態(tài)類型才有可能與靜態(tài)類型不同。如果表達式既不是引用也不是指針,則它的動態(tài)類型永遠與靜態(tài)類型一致。

4 . final和override

派生類中如果定義了一個函數(shù)與基類中虛函數(shù)同名但形參列表不同,編譯器會認為這是派生類新定義的函數(shù)。如果我們的意圖本是覆蓋虛函數(shù),則這種錯誤很難發(fā)現(xiàn)。通過在派生類中的虛函數(shù)最后加override關鍵字使得意圖更加清晰。如果我們使用override標記了某個函數(shù),但該函數(shù)并沒有覆蓋已存在的虛函數(shù),編譯器將報錯。

class Base{ // 基類 
public: 
  virtual int func(int a, int b) const; 
}; 
 
class Derive_Class : public Base{ 
public: 
  int func(int a) const override; // 報錯,沒有覆蓋虛函數(shù) 
}; 

如果我們定義一個類,并不希望它被繼承。或者希望某個函數(shù)不被覆蓋,則可以把類或者函數(shù)指定為final,則之后任何嘗試繼承該類或覆蓋該函數(shù)的操作將引發(fā)錯誤。

class Base final { /*  */ };   // 基類不能被繼承 
class Derive_Class : public Base { /* */ };   // 報錯 
 
void func(int) const final;  // 不允許后續(xù)的其他類覆蓋func(int)

5 . 回避虛函數(shù)的機制

在某些情況下,我們希望對虛函數(shù)的調(diào)用不要進行動態(tài)綁定,而是強迫其執(zhí)行虛函數(shù)的某個特定版本??梢允褂米饔糜蜻\算符實現(xiàn)這一目的。

// 強行調(diào)用基類中定義的函數(shù)版本而不管baseP的動態(tài)類型是什么 
int a = baseP->Base::func(42); 

如果一個派生類虛函數(shù)需要調(diào)用它的基類版本,但是沒有使用作用域運算符,則在運行時該調(diào)用將被解析為對派生類版本自身的調(diào)用,從而導致無限遞歸。

二、純虛函數(shù)

1 . 定義

為了方便使用多態(tài)特性,我們常常需要在基類中定義虛函數(shù)。在許多情況下,在基類中不能對虛函數(shù)給出有意義的實現(xiàn)。為了讓虛函數(shù)在基類什么也不做,引進了“純虛函數(shù)”的概念,使函數(shù)無須定義。我們通過在函數(shù)體的位置(即在聲明語句的分號之前)書寫=0就可以將一個虛函數(shù)說明為純虛函數(shù)(pure virtual)。其中,=0只能出現(xiàn)在類內(nèi)部的虛函數(shù)聲明語句處:

class Base{ // 抽象基類 
public: 
  virtual int func(int n) const =0; 
}; 

需要注意的是,我們也可以為純虛函數(shù)提供定義,不過函數(shù)體必須定義在類的外部。

2 . 抽象基類

含有(或者未經(jīng)覆蓋直接繼承)純虛函數(shù)的類叫抽象基類(abstract base class)。抽象基類負責定義接口,而后續(xù)的其他類可以覆蓋該接口。如果派生類中沒有重新定義純虛函數(shù),而只是繼承基類的純虛函數(shù),則這個派生類仍然還是一個抽象基類。因為抽象基類含有純虛函數(shù)(沒有定義),所以我們不能創(chuàng)建一個抽象基類的對象,但可以聲明指向抽象基類的指針或引用。

Base base;  // 錯誤,不能實例化抽象基類 

總結:

①.虛函數(shù)必須實現(xiàn),不實現(xiàn)編譯器會報錯。

②.父類和子類都有各自的虛函數(shù)版本。由多態(tài)方式在運行時動態(tài)綁定。

③.通過作用域運算符可以強行調(diào)用指定的虛函數(shù)版本。

④.純虛函數(shù)聲明如下:virtual void funtion()=0; 純虛函數(shù)無需定義。包含純虛函數(shù)的類是抽象基類,抽象基類不能創(chuàng)建對象,但可以聲明指向抽象基類的指針或引用。

⑤.派生類實現(xiàn)了純虛函數(shù)以后,該純虛函數(shù)在派生類中就變成了虛函數(shù),其子類可以再對該函數(shù)進行覆蓋。

⑥.析構函數(shù)通常應該是虛函數(shù),這樣就能確保在析構時調(diào)用正確的析構函數(shù)版本。

相關文章

  • C++實現(xiàn)簡易的五子棋小游戲

    C++實現(xiàn)簡易的五子棋小游戲

    這篇文章主要為大家詳細介紹了C++實現(xiàn)簡易的五子棋小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Vscode配置C/C++環(huán)境使用minGW(保姆級配置過程)

    Vscode配置C/C++環(huán)境使用minGW(保姆級配置過程)

    本文主要介紹了Vscode配置C/C++環(huán)境使用minGW(保姆級配置過程),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 一起來了解一下C++中的指針

    一起來了解一下C++中的指針

    這篇文章主要為大家詳細介紹了C++的指針,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • c++實現(xiàn)單純形法現(xiàn)行規(guī)劃問題的求解(推薦)

    c++實現(xiàn)單純形法現(xiàn)行規(guī)劃問題的求解(推薦)

    這篇文章主要介紹了c++實現(xiàn)單純形法現(xiàn)行規(guī)劃問題的求解,本文針對問題通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • C語言斷言函數(shù)assert()的學習筆記

    C語言斷言函數(shù)assert()的學習筆記

    在C語言庫函數(shù)中提供了一個輔助調(diào)試程序的小型庫,它是由assert()宏組成,本文就詳細的介紹了一下如何使用,感興趣的可以了解一下
    2021-11-11
  • VC實現(xiàn)對話框窗口任意分割

    VC實現(xiàn)對話框窗口任意分割

    最近寫MFC的程序,想在對話框里實現(xiàn)窗口的任意分割?,F(xiàn)在網(wǎng)絡資料一大抄,找個東西實在麻煩??偹氵@個很簡單,很快就搞定了,寫下來做個筆記。
    2015-06-06
  • 簡單總結C語言中各種類型的指針的概念

    簡單總結C語言中各種類型的指針的概念

    這篇文章主要簡單總結了C語言中各種類型的指針的概念,指針可以說是C語言本身所具有的最大特性,平時根據(jù)不同使用場合習慣地將其簡單分類,需要的朋友可以參考下
    2016-03-03
  • c++11 atomic的使用詳解

    c++11 atomic的使用詳解

    這篇文章主要介紹了c++11 atomic的使用詳解,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下
    2021-02-02
  • QT QML的元素布局的實現(xiàn)

    QT QML的元素布局的實現(xiàn)

    這篇文章主要介紹了QT QML的元素布局的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-02-02
  • C語言?推理證明帶環(huán)鏈表詳細過程

    C語言?推理證明帶環(huán)鏈表詳細過程

    單鏈表中同樣也有具有挑戰(zhàn)性的題目,鏈表的帶環(huán)問題可以說是眾多難題中的佼佼者,在這里可能更看重的是邏輯推理和證明的過程
    2022-04-04

最新評論