前言
虛函數是在類中被聲明為virtual的成員函數,當編譯器看到通過指標或引用調用此類函數時,對其執行晚綁定,即通過指標(或引用)指向的類的類型資訊來決定該函數是哪個類的。通常此類指標或引用都聲明為基類的,它可以指向基類或衍生類別的對象。通過類繼承和虛函數機制可以實現C++運行期的動態多態。
虛函數
虛函數是動態多態性的基礎,其調用的方式是動態聯編(又稱晚期聯編,簡單解釋為只有在程式運行時才決定調用基類的還是子類的,系統會根據基類指標所指向的對象來決定要調用的函數)。
非虛函數與其相反,是靜態聯編(調用已經在編譯時間期就決定了;在編譯時間期,系統已經根據指標所屬的類型確定了要調用的函數)。
在定義了虛函數後,可以在基類的衍生類別中對虛函數重新定義,在衍生類別中重新定義的函數應與虛函數具有相同的形參個數和形參類型。以實現統一的介面,不同定義過程。如果在衍生類別中沒有對虛函數重新定義,則它繼承其基類的虛函數,例子如下:
// virtual members
#include <iostream>
using namespace std;
class CPolygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
virtual int area ()
{ return (0); }
};
class CRectangle: public CPolygon {
public:
int area ()
{ return (width * height); }
};
class CTriangle: public CPolygon {
public:
int area ()
{ return (width * height / 2); }
};
int main () {
CRectangle rect;
CTriangle trgl;
CPolygon poly;
CPolygon * ppoly1 = ▭
CPolygon * ppoly2 = &trgl;
CPolygon * ppoly3 = &poly;
ppoly1->set_values (4,5);
ppoly2->set_values (4,5);
ppoly3->set_values (4,5);
cout << ppoly1->area() << endl;
cout << ppoly2->area() << endl;
cout << ppoly3->area() << endl;
return 0;
}
純虛函數
如果父類的函數(方法)根本沒有必要或者無法實現,完全要依賴子類去實現的話,可以把此函數(方法)設為virtual 函數名=0 我們把這樣的函數(方法)稱為純虛函數。
如果一個類包含了純虛函數,稱此類為抽象類別,抽象類別是不能執行個體化的。
一個抽象基類CPolygon可能看起來像這樣:
// abstract class CPolygon
class CPolygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
virtual int area () =0;
};
一個類不能執行個體化對象,不是完全沒有用處。我們可以建立它的指標,並充分利用它的多態能力。因此,聲明如下:
CPolygon * ppoly1;
CPolygon * ppoly2;
CPolygon包含一個純虛函數,因此它是一個抽象基類。然而,這個抽象基類的指標可以用來指向衍生類別的對象。
完整樣本如下:
// abstract base class
#include <iostream>
using namespace std;
class CPolygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
virtual int area (void) =0;
};
class CRectangle: public CPolygon {
public:
int area (void)
{ return (width * height); }
};
class CTriangle: public CPolygon {
public:
int area (void)
{ return (width * height / 2); }
};
int main () {
CRectangle rect;
CTriangle trgl;
CPolygon * ppoly1 = ▭
CPolygon * ppoly2 = &trgl;
ppoly1->set_values (4,5);
ppoly2->set_values (4,5);
cout << ppoly1->area() << endl;
cout << ppoly2->area() << endl;
return 0;
}