一、純虛函數定義.
純虛函數是在基類中聲明的虛函數,它在基類中沒有定義,但要求任何派生類都要定義自己的實現方法。在基類中實現純虛函數的方法是在函數原型後加“=0”
二、引入原因:
1、為了方便使用多態特性,我們常常需要在基類中定義虛擬函數。
2、在很多情況下,基類本身生成對象是不合情理的。例如,動物作為一個基類可以派生出老虎、孔雀等子類,但動物本身生成對象明顯不合常理。
為了解決上述問題,引入了純虛函數的概念,將函數定義為純虛函數(方法:virtual ReturnType Function()= 0;),則編譯器要求在派生類中必須予以重載以實現多態性。同時含有純虛擬函數的類稱為抽象類,它不能生成對象。這樣就很好地解決了上述兩個問題。
三、相似概念:
1、多態性
指相同對象收到不同消息或不同對象收到相同消息時產生不同的實現動作。C++支持兩種多態性:編譯時多態性,運行時多態性。
a.編譯時多態性: 通過函數重載和運算符重載來實現的。
b 運行時多態性:通過繼承和虛函數來實現的。
2、虛函數
虛函數是在基類中被聲明為virtual,並在派生類中重新定義的成員函數,可實現成員函數的動態重載
純虛函數的聲明有著特殊的語法格式:virtual 返回值類型成員函數名(參數表)=0;
請注意,純虛函數應該只有聲明,沒有具體的定義,即使給出了純虛函數的定義也會被編譯器忽略。
3、抽象類
包含純虛函數的類稱為抽象類。由於抽象類包含了沒有定義的純虛函數,所以不能定義抽象類的對象。
在C++中,我們可以把只能用於被繼承而不能直接創建對象的類設置為抽象類(Abstract Class)。
之所以要存在抽象類,最主要是因為它具有不確定因素。我們把那些類中的確存在,但是在父類中無法確定具體實現的成員函數稱為純虛函數。純虛函數是一種 特殊的虛函數,它只有聲明,沒有具體的定義。抽象類中至少存在一個純虛函數;存在純虛函數的類一定是抽象類。存在純虛函數是成為抽象類的充要條件。
1 //基類: 2 class A 3 { 4 public: 5 A(); 6 void f1(); 7 virtual void f2(); 8 virtual void f3()=0; 9 virtual ~A(); 10 }; 11 12 //子類: 13 class B : public A 14 { 15 public: 16 B(); 17 void f1(); 18 void f2(); 19 void f3(); 20 virtual ~B(); 21 }; 22 23 //主函數: 24 int main(int argc, char* argv[]) 25 { 26 A *m_j=new B(); 27 m_j->f1(); 28 m_j->f2(); 29 m_j->f3(); 30 delete m_j; 31 return 0; 32 } 33 /* 34 f1()是一個普通的重載. 35 調用m_j->f1();會去調用A類中的f1(),它是在我們寫好代碼的時候就會定好的.因為f1()不是虛函數,不會動態綁定 36 也就是根據它是由A類定義的,這樣就調用這個類的函數. 37 f2()是虛函數. 38 調用m_j->f2();會調用m_j中保存的對象中,對應的這個函數.這是由於new的B對象. 39 f3()與f2()一樣,只是在基類中不需要寫函數實現. 40 */
抽象類是為了抽象和設計的目的而建立的,處於繼承層次結構的上層。
具體類是能夠建立對象的類。
抽象類的規定
(1)抽象類只能用作其他類的基類,不能建立抽象類對象。
(2)抽象類不能用作參數類型、函數返回類型或顯式轉換的類型。
(3)可以定義指向抽象類的指針和引用,此指針可以指向它的派生類,進而實現多態性。
#include<iostream> using namespace std; const double PI=3.14159; class Shapes //抽象類 { protected: int x, y; public: void setvalue(int d, int w=0){x=d;y=w;} virtual void disp()=0;//純虛函數 }; class Square:public Shapes { public: void disp(){ cout<<"矩形面積:"<<x*y<<endl; } }; class Circle:public Shapes{ public: void disp(){ cout<<"圓面積:"<<PI*x*x<<endl; } }; int main() { Shapes *ptr[2]; //定義對象指針數組 Square s1; Circle c1; ptr[0] = &s1; ptr[0]->setvalue(10, 5); ptr[0]->disp(); ptr[1] = &c1; ptr[1]->setvalue(10); ptr[1]->disp(); return 0; }