C++ 多型

C++ 多型

多型按字面的意思就是多種形態。當類之間存在層次結構,並且類之間是通過繼承關聯時,就會用到多型。

C++ 多型意味著呼叫成員函式時,會根據呼叫函式的物件的型別來執行不同的函式。

下面的例項中,基類 Shape 被派生為兩個類,如下所示:

例項

#include <iostream> using namespace std; class Shape { protected: int width, height; public: Shape( int a=0, int b=0) { width = a; height = b; } int area() { cout << "Parent class area :" <<endl; return 0; } }; class Rectangle: public Shape{ public: Rectangle( int a=0, int b=0):Shape(a, b) { } int area () { cout << "Rectangle class area :" <<endl; return (width * height); } }; class Triangle: public Shape{ public: Triangle( int a=0, int b=0):Shape(a, b) { } int area () { cout << "Triangle class area :" <<endl; return (width * height / 2); } }; // 程式的主函式 int main( ) { Shape *shape; Rectangle rec(10,7); Triangle tri(10,5); // 儲存矩形的地址 shape = &rec; // 呼叫矩形的求面積函式 area shape->area(); // 儲存三角形的地址 shape = &tri; // 呼叫三角形的求面積函式 area shape->area(); return 0; }

當上面的程式碼被編譯和執行時,它會產生下列結果:

Parent class area
Parent class area

導致錯誤輸出的原因是,呼叫函式 area() 被編譯器設定為基類中的版本,這就是所謂的靜態多型,或靜態連結 - 函式呼叫在程式執行前就準備好了。有時候這也被稱為早繫結,因為 area() 函式在程式編譯期間就已經設定好了。

但現在,讓我們對程式稍作修改,在 Shape 類中,area() 的宣告前放置關鍵字 virtual,如下所示:

class Shape { protected: int width, height; public: Shape( int a=0, int b=0) { width = a; height = b; } virtual int area() { cout << "Parent class area :" <<endl; return 0; } };

修改後,當編譯和執行前面的例項程式碼時,它會產生以下結果:

Rectangle class area
Triangle class area

此時,編譯器看的是指標的內容,而不是它的型別。因此,由於 tri 和 rec 類的物件的地址儲存在 *shape 中,所以會呼叫各自的 area() 函式。

正如您所看到的,每個子類都有一個函式 area() 的獨立實現。這就是多型的一般使用方式。有了多型,您可以有多個不同的類,都帶有同一個名稱但具有不同實現的函式,函式的引數甚至可以是相同的。

虛擬函式

虛擬函式 是在基類中使用關鍵字 virtual 宣告的函式。在派生類中重新定義基類中定義的虛擬函式時,會告訴編譯器不要靜態連結到該函式。

我們想要的是在程式中任意點可以根據所呼叫的物件型別來選擇呼叫的函式,這種操作被稱為動態連結,或後期繫結

純虛擬函式

您可能想要在基類中定義虛擬函式,以便在派生類中重新定義該函式更好地適用於物件,但是您在基類中又不能對虛擬函式給出有意義的實現,這個時候就會用到純虛擬函式。

我們可以把基類中的虛擬函式 area() 改寫如下:

class Shape { protected: int width, height; public: Shape( int a=0, int b=0) { width = a; height = b; } // pure virtual function virtual int area() = 0; };

= 0 告訴編譯器,函式沒有主體,上面的虛擬函式是純虛擬函式