C++多態
這個詞多態是指有多種形式。通常情況下,當有一個類層次並且它們通過繼承關係產生多態。
C++多態意味著調用一個成員函數將產生不同的功能結果,以根據所調用的函數的對象的類型來執行。
考慮下麵的例子,其中一個基類是來自其它兩個類:
#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); } }; // Main function for the program int main( ) { Shape *shape; Rectangle rec(10,7); Triangle tri(10,5); // store the address of Rectangle shape = &rec; // call rectangle area. shape->area(); // store the address of Triangle shape = &tri; // call triangle area. shape->area(); return 0; }
讓我們編譯和運行上麵的程序,這將產生以下結果:
Parent class area Parent class area
不正確的輸出是調用函數area() 的原因是由編譯器在基類中定義的版本設置的。這就是所謂的靜態解析函數調用,或靜態鏈接- 在執行程序之前的函數調用是固定的。此有時也被稱為早期綁定,因為area()函數在程序彙編時設置。
但現在,讓我們在我們的程序稍作修改和聲明area() ,在Shape類的前麵加上關鍵字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()函數。這是是如何多態通常使用。不同的類具有相同函數名稱,並且即使相同的參數,但也可以有不同的實現。
虛擬函數:
虛函數是在使用關鍵字的虛擬聲明的基類的函數。定義在基類中的虛函數,與其他版本在派生類不同,我們不希望這個函數靜態鏈接編譯器。
我們所要的是函數的選擇被調用在程序中任何給定的點是基於用於調用它的類的對象。這種操作被稱為動態鏈接,或後期綁定。
純虛函數:
這是可能的,想包括在基類中的虛函數,以便它可以在派生類中被重新定義,以適應該類的對象,但冇有實際的定義,可以在基類中聲明函數。
我們可以改變所述虛擬函數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表明該函數冇有主體和上述虛函數被編譯器調用。