C++多態 Polymorphism 本文為C++官網對多態闡述:http://www.cplusplus.com/doc/tutorial/polymorphism/ 在瞭解多態前需具備如下知識:類、結構體、友元和繼承。 指向基類的指針 先來看一個基礎例子 1 // pointers to bas ...
C++多態
Polymorphism
本文為C++官網對多態闡述:http://www.cplusplus.com/doc/tutorial/polymorphism/
在瞭解多態前需具備如下知識:類、結構體、友元和繼承。
指向基類的指針
先來看一個基礎例子
1 // pointers to base class 2 #include <iostream> 3 using namespace std; 4 5 class Polygon { 6 protected: 7 int width, height; 8 public: 9 void set_values (int a, int b) 10 { width=a; height=b; } 11 }; 12 13 class Rectangle: public Polygon { 14 public: 15 int area() 16 { return width*height; } 17 }; 18 19 class Triangle: public Polygon { 20 public: 21 int area() 22 { return width*height/2; } 23 }; 24 25 int main () { 26 Rectangle rect; 27 Triangle trgl; 28 Polygon * ppoly1 = ▭ 29 Polygon * ppoly2 = &trgl; 30 ppoly1->set_values (4,5); 31 ppoly2->set_values (4,5); 32 cout << rect.area() << '\n'; 33 cout << trgl.area() << '\n'; 34 return 0; 35 }pointers to base class
在Rectangle和Triangle類中都含有函數area()。main函數中是分別用類對象直接調用。由於Polygon類中沒有area成員函數,故ppoly1和ppoly2指針無法調用該函數。如果在基類中也能調用area()那麼就不用上面代碼中分別調用那麼麻煩了,不過問題是area()方法不統一,沒法在基類中實現。
虛成員
虛成員是一種能在派生類中重定義的成員函數,通過關鍵字 virtual 聲明。
1 // virtual members 2 #include <iostream> 3 using namespace std; 4 5 class Polygon { 6 protected: 7 int width, height; 8 public: 9 void set_values (int a, int b) 10 { width=a; height=b; } 11 virtual int area () 12 { return 0; } 13 }; 14 15 class Rectangle: public Polygon { 16 public: 17 int area () 18 { return width * height; } 19 }; 20 21 class Triangle: public Polygon { 22 public: 23 int area () 24 { return (width * height / 2); } 25 }; 26 27 int main () { 28 Rectangle rect; 29 Triangle trgl; 30 Polygon poly; 31 Polygon * ppoly1 = ▭ 32 Polygon * ppoly2 = &trgl; 33 Polygon * ppoly3 = &poly; 34 ppoly1->set_values (4,5); 35 ppoly2->set_values (4,5); 36 ppoly3->set_values (4,5); 37 cout << ppoly1->area() << '\n'; 38 cout << ppoly2->area() << '\n'; 39 cout << ppoly3->area() << '\n'; 40 return 0; 41 }virtual members
輸出結果:
20
10
0
在Polygon類中函數 area 被聲明成 virtual 因為他將被每個派生類重定義。雖然沒有關鍵字 virtual 函數area也能派生類重定義,但是非虛成員不能被派生類通過基類引用訪問。如果此處area前的virtual關鍵字被去掉,上面三個cout結果都會是0,因為調用的時候會被基類的函數替代。
一個聲明或繼承了虛函數的類被叫做多態類。
抽象基類
抽象基類是只能被當作基類,從而被允許擁有未定義的虛成員函數(純虛函數)。
1 // abstract class CPolygon 2 class Polygon { 3 protected: 4 int width, height; 5 public: 6 void set_values (int a, int b) 7 { width=a; height=b; } 8 virtual int area () =0; 9 };abstract class
註意此時 area函數未定義;他的定義被=0取代,這使它變成了一個純虛函數。至少擁有一個純虛函數的類叫做抽象基類。抽象類不能被實例化,但能使用其指針。
1 // abstract base class 2 #include <iostream> 3 using namespace std; 4 5 class Polygon { 6 protected: 7 int width, height; 8 public: 9 void set_values (int a, int b) 10 { width=a; height=b; } 11 virtual int area (void) =0; 12 }; 13 14 class Rectangle: public Polygon { 15 public: 16 int area (void) 17 { return (width * height); } 18 }; 19 20 class Triangle: public Polygon { 21 public: 22 int area (void) 23 { return (width * height / 2); } 24 }; 25 26 int main () { 27 Rectangle rect; 28 Triangle trgl; 29 Polygon * ppoly1 = ▭ 30 Polygon * ppoly2 = &trgl; 31 ppoly1->set_values (4,5); 32 ppoly2->set_values (4,5); 33 cout << ppoly1->area() << '\n'; 34 cout << ppoly2->area() << '\n'; 35 return 0; 36 }abstract base class
這個例子中都是由基類Polygon指針調用成員函數。還能在基類中使用this指針調用派生類繼承的純虛函數。
1 // pure virtual members can be called 2 // from the abstract base class 3 #include <iostream> 4 using namespace std; 5 6 class Polygon { 7 protected: 8 int width, height; 9 public: 10 void set_values (int a, int b) 11 { width=a; height=b; } 12 virtual int area() =0; 13 void printarea() 14 { cout << this->area() << '\n'; } 15 }; 16 17 class Rectangle: public Polygon { 18 public: 19 int area (void) 20 { return (width * height); } 21 }; 22 23 class Triangle: public Polygon { 24 public: 25 int area (void) 26 { return (width * height / 2); } 27 }; 28 29 int main () { 30 Rectangle rect; 31 Triangle trgl; 32 Polygon * ppoly1 = ▭ 33 Polygon * ppoly2 = &trgl; 34 ppoly1->set_values (4,5); 35 ppoly2->set_values (4,5); 36 ppoly1->printarea(); 37 ppoly2->printarea(); 38 return 0; 39 }pure virtual members can be called from the abstract base class
虛成員和抽象類賦予了C++多態特性,對面向對象項目用於極大。
以下的例子結合了動態記憶體、類構造初始化、多態:
1 // dynamic allocation and polymorphism 2 #include <iostream> 3 using namespace std; 4 5 class Polygon { 6 protected: 7 int width, height; 8 public: 9 Polygon (int a, int b) : width(a), height(b) {} 10 virtual int area (void) =0; 11 void printarea() 12 { cout << this->area() << '\n'; } 13 }; 14 15 class Rectangle: public Polygon { 16 public: 17 Rectangle(int a,int b) : Polygon(a,b) {} 18 int area() 19 { return width*height; } 20 }; 21 22 class Triangle: public Polygon { 23 public: 24 Triangle(int a,int b) : Polygon(a,b) {} 25 int area() 26 { return width*height/2; } 27 }; 28 29 int main () { 30 Polygon * ppoly1 = new Rectangle (4,5); 31 Polygon * ppoly2 = new Triangle (4,5); 32 ppoly1->printarea(); 33 ppoly2->printarea(); 34 delete ppoly1; 35 delete ppoly2; 36 return 0; 37 }dynamic allocation and polymorphism
此處基類指針聲明時直接用的派生類。