開心檔之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 告訴編譯器,函式沒有主體,上面的虛擬函式是 純虛擬函式。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70026554/viewspace-2944162/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 開心檔之C++ 修飾符型別C++型別
- 開心檔之C++ 引用C++
- 開心檔之C++ 運算子C++
- 開心檔之C++ 數字C++
- 開心檔之C++ 訊號處理C++
- 開心檔之C++ 前處理器C++
- 開心檔之Java 變數型別Java變數型別
- 開心檔之Go教程Go
- 開心檔之MySQL 管理MySql
- 開心檔之C++ 過載運算子和過載函式C++函式
- C++多型之虛擬函式C++多型函式
- 開心檔之Go 併發Go
- 開心檔之MySQL ALTER命令MySql
- C++——多型C++多型
- C++多型C++多型
- 開心檔之MySQL 複製表MySql
- 開心檔之Go 語言常量Go
- 開心檔之Java 9 新特性Java
- 開心檔之python 推導式Python
- 開心檔之Vue.js 路由Vue.js路由
- 開心檔之Go 錯誤處理Go
- 開心檔之MySQL 正規表示式MySql
- 開心檔之Java switch case 語句Java
- 深入理解 C++ 中的多型與檔案操作C++多型
- 開心檔之Go 語言環境安裝Go
- 開心檔之Python3 資料結構Python資料結構
- C++整理16_多型C++多型
- c++學習心得第二期 多型+檔案操作C++多型
- 【C++】C++之型別轉換C++型別
- C++八股之函式過載與重寫-靜態多型與動態多型C++函式多型
- C++ 多型的實現及原理C++多型
- [c++] 繼承和多型整理二C++繼承多型
- C++之string型別詳解C++型別
- vscode除錯多C++檔案專案VSCode除錯C++
- 開心檔-軟體開發入門教程網之Node.js 回撥函式Node.js函式
- Visual C++ 6.0專案檔案型別簡介C++型別
- 開心檔-Node.js入門篇2Node.js
- c++菱形繼承、多型與類記憶體模型C++繼承多型記憶體模型