程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++中虛函數與純虛函數的用法

C++中虛函數與純虛函數的用法

編輯:關於C++

C++中虛函數與純虛函數的用法。本站提示廣大學習愛好者:(C++中虛函數與純虛函數的用法)文章只能為提供參考,不一定能成為您想要的結果。以下是C++中虛函數與純虛函數的用法正文


本文較為深刻的剖析了C++中虛函數與純虛函數的用法,關於進修和控制面向對象法式設計來講是相當主要的。詳細內容以下:

起首,面向對象法式設計(object-oriented programming)的焦點思惟是數據籠統、繼續、靜態綁定。經由過程數據籠統,可使類的接口與完成分別,應用繼續,可以更輕易地界說與其他類類似但不完整雷同的新類,應用靜態綁定,可以在必定水平上疏忽類似類的差別,而以同一的方法應用它們的對象。

虛函數的感化是完成多態性(Polymorphism),多態性是將接口與完成停止分別,采取配合的辦法,但因個別差別而采取分歧的戰略。純虛函數則是一種特別的虛函數。虛函數接洽到多態,多態接洽到繼續。所以本文中都是在繼續條理上做文章。沒了繼續,甚麼都沒得談。

1、虛函數

1 . 界說

在C++中,基類必需將它的兩種成員函數辨別開來:一種是基類願望其派生類停止籠罩的函數;另外一種是基類願望派生類直接繼續而不要轉變的函數。關於前者,基類經由過程在函數之前加上virtual症結字將其界說為虛函數(virtual)。

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

當我們在派生類中籠罩某個函數時,可以在函數前加virtual症結字。但是這不是必需的,由於一旦某個函數被聲明成虛函數,則一切派生類中它都是虛函數。任何結構函數以外的非靜態函數都可所以虛函數。派生類常常(但不老是)籠罩它繼續的虛函數,假如派生類沒有籠罩其基類中某個虛函數,則該虛函數的行動相似於其他的通俗成員,派生類會直接繼續其在基類中的版本。

2 . 靜態綁定

當我們應用基類的援用(或指針)挪用一個虛函數時將產生靜態綁定(dynamic binding)。由於我們直到運轉時能力曉得究竟挪用了哪一個版本的虛函數,能夠是基類中的版本也能夠是派生類中的版本,斷定的根據是援用(或指針)所綁定的對象的真實類型。與非虛函數在編譯時綁定分歧,虛函數是在運轉時選擇函數的版本,所以靜態綁定也叫運轉時綁定(run-time binding)。

3 . 靜態類型與靜態類型

靜態類型指的是變量聲明時的類型或表達式生成的類型,它在編譯時老是已知的;靜態類型指的是變量或表達式表現的內存中的對象的類型,它直到運轉時才可知。當且僅當經由過程基類的指針或援用挪用虛函數時,才會在運轉時解析該挪用,也只要在這類情形下對象的靜態類型才有能夠與靜態類型分歧。假如表達式既不是援用也不是指針,則它的靜態類型永久與靜態類型分歧。

4 . final和override

派生類中假如界說了一個函數與基類中虛函數同名但形參列表分歧,編譯器會以為這是派生類新界說的函數。假如我們的意圖本是籠罩虛函數,則這類毛病很難發明。經由過程在派生類中的虛函數最初加override症結字使自得圖加倍清楚。假如我們應用override標志了某個函數,但該函數並沒有籠罩已存在的虛函數,編譯器將報錯。

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

假如我們界說一個類,其實不願望它被繼續。或許願望某個函數不被籠罩,則可以把類或許函數指定為final,則以後任未嘗試繼續該類或籠罩該函數的操作將激發毛病。

class Base final { /*  */ };   // 基類不克不及被繼續 
class Derive_Class : public Base { /* */ };   // 報錯 
 
void func(int) const final;  // 不許可後續的其他類籠罩func(int)

5 . 躲避虛函數的機制

在某些情形下,我們願望對虛函數的挪用不要停止靜態綁定,而是強制其履行虛函數的某個特定版本。可使用感化域運算符完成這一目標。

// 強行挪用基類中界說的函數版本而不論baseP的靜態類型是甚麼 
int a = baseP->Base::func(42); 

假如一個派生類虛函數須要挪用它的基類版本,然則沒有應用感化域運算符,則在運轉時該挪用將被解析為對派生類版本本身的挪用,從而招致無窮遞歸。

2、純虛函數

1 . 界說

為了便利應用多態特征,我們經常須要在基類中界說虛函數。在很多情形下,在基類中不克不及對虛函數給出成心義的完成。為了讓虛函數在基類甚麼也不做,引進了“純虛函數”的概念,使函數不必界說。我們經由過程在函數體的地位(即在聲明語句的分號之前)書寫=0便可以將一個虛函數解釋為純虛函數(pure virtual)。個中,=0只能湧現在類外部的虛函數聲明語句處:

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

須要留意的是,我們也能夠為純虛函數供給界說,不外函數體必需界說在類的內部。

2 . 籠統基類

含有(或許未經籠罩直接繼續)純虛函數的類叫籠統基類(abstract base class)。籠統基類擔任界說接口,爾後續的其他類可以籠罩該接口。假如派生類中沒有從新界說純虛函數,而只是繼續基類的純虛函數,則這個派生類依然照樣一個籠統基類。由於籠統基類含有純虛函數(沒有界說),所以我們不克不及創立一個籠統基類的對象,但可以聲明指向籠統基類的指針或援用。

Base base;  // 毛病,不克不及實例化籠統基類 

總結:

①.虛函數必需完成,不完成編譯器會報錯。

②.父類和子類都有各自的虛函數版本。由多態方法在運轉時靜態綁定。

③.經由過程感化域運算符可以強行挪用指定的虛函數版本。

④.純虛函數聲明以下:virtual void funtion()=0; 純虛函數無需界說。包括純虛函數的類是籠統基類,籠統基類不克不及創立對象,但可以聲明指向籠統基類的指針或援用。

⑤.派生類完成了純虛函數今後,該純虛函數在派生類中就釀成了虛函數,其子類可以再對該函數停止籠罩。

⑥.析構函數平日應當是虛函數,如許就可以確保在析構時挪用准確的析構函數版本。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved