多態性

多態性

進入本節之前,建議你有一個正確的理解指針和類繼承。 如果下面的語句似乎怪你,你應該檢討指定的章節: 

聲明: 解釋:
的INT A :: B(C){}
A-> B 數據結構
A級:公衆B {}; 友誼和繼承

基類的指針

派生類的主要特點之一是其基類的指針到派生類的指針類型兼容。 多態性是藝術趁着這個簡單但功能強大和靈活的功能,帶來了面向對象的方法,以充分發揮其潛力。 

我們要開始的矩形和三角形上一節考慮這指針兼容性屬性重寫我們的程序: 

1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 
 // pointers to 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; } }; 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 * ppoly1 = &rect; CPolygon * ppoly2 = &trgl; ppoly1->set_values (4,5); ppoly2->set_values (4,5); cout << rect.area() << endl; cout << trgl.area() << endl; return 0; } 
  20 
  10 


main函數中,我們創建了兩個指向,以對象類CPolygon(ppoly1 ppoly2)的。 然後我們分配引用rectTRGL的這些指針,因爲兩者都是CPolygon的派生類的對象,都是有效的分配操作。 

唯一的限制在使用* ppoly1* ppoly2代替rectTRGL的是,這兩個* ppoly1* ppoly2CPolygon的*類型,因此我們只能使用這些指針來引用, 類CRectangle和 CTriangle的繼承CPolygon的成員。 出於這個原因,當我們調用的區域()的節目結束時,我們不得不直接使用的對象rectTRGL的 ,而不是指針* ppoly1* ppoly2成員。 

CPolygon的指針以使用面積(),則該成員應也已宣佈在類CPolygon,不僅在它的派生類,但問題是, 類CRectangle和CTriangle的實施地區的不同版本,因此我們不能執行,在基類中。 這是虛擬成員時變得得心應手: 

虛擬成員

被稱爲虛擬成員的類的一個成員在​​派生類可以重新定義。 爲了申報一類作爲虛擬的一員,我們必須先聲明virtual關鍵字: 

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 
 // 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 = &rect; 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; } 
  20 
  10 
  0 


現在三類( 圈交 , 類CRectangle和 CTriangle的),有相同的成員: 寬度 , 高度中, 函數set_values()面積()。

區域()成員函數被聲明爲虛基類中的,因爲它是後來每個派生類中重新定義。 您可以驗證,如果你想,如果你刪除這個虛擬的關鍵字從申報區域()CPolygon的範圍內 ,然後運行程序,結果將是0三個多邊形,而不是20,100。 ,而不是調用相應區域()函數的每個對象(CRectangle的區域(),CTriangle ::面積()圈交::面積 ,這是因爲(),分別),將被稱爲圈交::面積()所有情況下,因爲這些調用是通過指針的類型是CPolygon的*。 

因此, 虛擬關鍵字的作用是允許一個派生類的成員具有相同的名稱作爲一個在基類中被適當地稱爲從一個指針,和更精確地,當不同的指針是一個指針到基類但指向派生的類的一個對象,如在上面的例子。 

聲明或繼承了虛函數的類稱爲多態類 。 

請注意,儘管它的虛擬性,我們也能夠CPolygon類型來聲明對象,並呼籲自己的領域()函數,它總是返回0。 

抽象基類

抽象基類的東西非常類似我們前面的例子我們CPolygon的類。 唯一的區別是,在我們前面的例子中,我們定義的有效面積()函數的的類CPolygon(如對象 )爲對象,用最少的功能,而在一個抽象基類,我們可以離開那個區域()成員在所有沒有實現的功能。 這是通過附加到函數聲明= 0(等於零)。 

一個抽象基CPolygon的類可能看起來像這樣: 

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 
 // 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; }; 


注意我們如何附加= 0虛擬的int區(),而不是指定一個實現的功能。 這種類型的函數稱爲純虛函數 ,所有至少包含一個純虛函數的類是抽象基類 。 

一個抽象基類和普通的多態類之間的主要區別是,因爲至少有一個抽象基類,其成員缺乏實現,我們不能創建它的實例(對象)。 

但也不是完全無用的一類,不能實例化對象。 我們可以創建指向它的指針,並充分利用其所有的多態能力。 因此,聲明如下: 

 
 CPolygon poly; 


不會有效的抽象基類,我們剛剛宣佈,因爲試圖實例化一個對象。 然而,下面的指針: 

 1 
 2 
 
 CPolygon * ppoly1; CPolygon * ppoly2; 


將是完全有效的。 

之所以如此,是CPolygon的 ,只要有一個純虛函數,因此它是一個抽象基類。 然而,可以使用這個抽象基類的指針指向派生類的對象。 

在這裏,你有完整的例子: 

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 
 // 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 = &rect; CPolygon * ppoly2 = &trgl; ppoly1->set_values (4,5); ppoly2->set_values (4,5); cout << ppoly1->area() << endl; cout << ppoly2->area() << endl; return 0; } 
  20 
  10 


如果您查看程序,你會發現,我們稱之爲不同的,但相關的類的對象使用一個獨特的類型的指針( 圈交*)。 這可以是相當有用的。 例如,現在我們可以創建一個函數成員的抽象基類CPolygon即能在屏幕上打印的區域()的結果CPolygon的本身功能,即使沒有實現這個功能: 

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 
 // pure virtual members can be called // from the 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; void printarea ( void ) { cout << this ->area() << endl; } }; 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 = &rect; CPolygon * ppoly2 = &trgl; ppoly1->set_values (4,5); ppoly2->set_values (4,5); ppoly1->printarea(); ppoly2->printarea(); return 0; } 
  20 
  10 


虛擬成員和抽象類出讓C + +的多態性面向對象編程的特點,使大項目中的一個有用的工具。 當然,我們已經看到了非常簡單的使用這些功能,但這些功能都可以應用到對象的數組或動態分配的對象。 

讓我們再次結束,同樣的例子,但這次與動態分配的對象: 

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 
 // dynamic allocation and polymorphism #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; void printarea ( void ) { cout << this ->area() << endl; } }; 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 () { CPolygon * ppoly1 = new CRectangle; CPolygon * ppoly2 = new CTriangle; ppoly1->set_values (4,5); ppoly2->set_values (4,5); ppoly1->printarea(); ppoly2->printarea(); delete ppoly1; delete ppoly2; return 0; } 
  20 
  10 


請注意,的ppoly指針: 

 1 
 2 
 
 CPolygon * ppoly1 = new CRectangle; CPolygon * ppoly2 = new CTriangle; 
發佈了58 篇原創文章 · 獲贊 0 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章