【C++學習筆記】虛擬函式(二)
阿新 • • 發佈:2018-12-23
虛擬函式與過載函式的關係
我們現在來比較一下規則比較多的虛擬函式和規則比較少的過載函式之間的差別:
-
普通函式過載時,其函式的引數個數或者引數型別必須有所不同,函式的返回型別也可以不同。(這個不同是比較嚴格的不同,是涉及本質的)
-
過載函式: 要求函式名、返回型別、引數個數、引數的型別和順序與基類中的虛擬函式完全相同。如果發生不同則分以下兩種情況:
1.返回值型別不同,其他相同-------->系統報錯
2.僅函式名相同,其他都不同--------->系統直接判其為過載,失去虛擬函式特徵。
總結:
- 可以看出過載函式是“因為相同,所以一定要找出點不同來方便靜態聯編去辨認。”而過載函式時“我相信動態聯編有這個辨識能力,所以我選擇都一樣,讓動態聯編自己去選擇。”
- 虛擬函式的條件比函式過載要嚴格,基本上除了函式體內具體操作,能一致的都保持一致了,一但有一點不同,系統就判為過載了。
純虛擬函式
純虛擬函式是一個在基類中說明的虛擬函式,它在該基類中沒有定義,但要求在它的派生類中必須定義自己的版本,或重新說明為純虛擬函式。
純虛擬函式的定義為:
virtual 函式型別 函式名(引數表)=0**;**//最後一個分號不要忘!
其實其主要區別就是書寫形式上在後面加了個“=0”,表明在基類中不用定義該函式,它的實現留給派生類去做。(純虛擬函式只是給了個名字而已,接下來怎麼實現都要靠後面派生類中的函式來構造,最後的“=0”只是個符號,不代表返回值為0).
假如一個類中聲明瞭純虛擬函式,而在其派生類中沒有對該函式的定義,則該虛擬函式在派生類中仍然為純虛擬函式。
抽象類
如果一個類中至少有一個純虛擬函式,那麼就稱該類為抽象類。
(抽象類和純虛擬函式是一個捆綁的概念,只要有了純虛擬函式就會有抽象類)
抽象類只能作為其他類的基類來使用,不能建立抽象類的物件,其純虛擬函式的實現由派生類給出。
派生類中必須過載類中純虛擬函式,系統會認為該類把純虛擬函式也繼承了,所以類內有純虛擬函式,會把該派生類視為抽象類,因此也不能定義自己的物件。
抽象類的幾點注意
標準化例子:
#include<iostream.h> class Circle{ //定義了純虛擬函式,Circle就變成了抽象類 public: void setr(int x){r=x;} //純虛擬函式雖然不能定義自己的物件但也可以// //定義成員以及成員函式,通過派生類的形式將 //其調用出來。 virtual void show()=0 //“=”0不表示返回值為0,是一個純虛擬函式符號 virtual~Circle() = 0; //解構函式也可以是純虛擬函式 protected: int r; }; class Area:public Circle { public: void show(){cout<<Area is <<3.14*r*r<<endl;} ~Area(){cout<<"The circle is deleted"<<endl;}//至少提供一種純虛擬函式的實現方案 }; class Perimeter:public Circle{ public: void show(){cout<<"Perimeter is"<<2*3.14*r<<endl;} ~Perimeter(){cout<<"The circle is deleted"<<endl;}//至少提供一種純虛擬函式的實現方案 }; void main() { Circle *ptr; Circle ptr; //此處是錯誤用法,不能用抽象類定義物件。 Area ob1; Perimeter ob2; ob1.setr(10); ob2.setr(10); ptr = &ob1; ptr->show(); ptr = &ob2(); ptr->show(); }
- 再次強調,不能建立抽象類的物件,但是可以建立抽象類的指標和引用,但這個指標是指向其派生類的,是為了實現其多型性的。
- 不允許從具體類派生出抽象類。(只允許從虛的派生出具體的,不能從具體的派生出虛的。)
- 抽象類既然不能定義物件,當然也不能作為引數型別、函式返回值或是顯式轉換型別。
- 解構函式也可以實現純虛擬函式,這時,應該至少提供一個實現。