一、多態簡介
什麼是“多態”:派生類對象的地址可以賦值給基類指針。對於通過基類指針調用基類和派生類中都有的同名、同參數表的虛函數的語句,編譯時並不確定要執行的是基類還是派生類的虛函數;而當程序運行到該語句時,如果基類指針指向的是一個基類對象,則基類的虛函數被調用,如果基類指針指向的是一個派生類對象,則派生類的虛函數被調用。這種機制就叫作“多態(polymorphism)”。
所謂“虛函數”,就是在聲明時前面加了 virtual 關鍵字的成員函數。virtual 關鍵字只在類定義中的成員函數聲明處使用,不能在類外部寫成員函數體時使用。使用時,其會告訴編譯器不要靜態鏈接到改函數,也就是說其在程序中任意點可以根據所調用的對象類型來選擇調用的函數,被稱爲動態鏈接或者後期綁定。注意:靜態成員函數不能是虛函數。
簡單的理解就是同一個事物在不同場景下的多種形態。
二、多態分類
三、靜態多態
函數重載就是一個簡單的靜態多態,一個簡單的例子
#include<iostream>
using namespace std;
int Add(int a, int b)
{
return a + b;
}
double Add(double a, int b)
{
return a + b;
}
int main()
{
Add(1, 2);
//Add(1.0, 2.0); //這是錯誤寫法
Add(1.0,2); //正確寫法
return 0;
}
代碼很簡單,不過多講述。
四、動態多態
還是舉一個簡單的例子:
#include <iostream>
using namespace std;
class A
{
public:
virtual void Print() { cout << "A::Print" << endl; }
};
class B : public A
{
public:
virtual void Print() { cout << "B::Print" << endl; }
};
class D : public A
{
public:
virtual void Print() { cout << "D::Print" << endl; }
};
class E : public B
{
virtual void Print() { cout << "E::Print" << endl; }
};
int main()
{
A a; B b; D d; E e;
A *pa = &a; B *pb = &b;
pa->Print(); //多態, a.Print()被調用,輸出:A::Print
pa = pb; //基類指針pa指向派生類對象b
pa->Print(); //b.Print()被調用,輸出:B::Print
pa = &d; //基類指針pa指向派生類對象d
pa->Print(); //多態, d. Print ()被調用,輸出:D::Print
pa = &e; //基類指針pa指向派生類對象d
pa->Print(); //多態, e.Print () 被調用,輸出:E::Print
return 0;
}
打印結果如下:
他們的派生關係如下:
在程序執行pa->Print();時,pa指向基類對象a,因此調用的就是類A的Print成員函數;執行pa=pb;pa->Print();時,pa指向的是類B的對象,因此調用的是類B的Print成員函數;執行pa=&d;pa->Print();時也是如此;類E是類A的間接派生類,因此,執行pa=&e;pa->Print();時,多態規則仍舊適用,此時pa指向派生類E的對象,所以調用的是E的Print成員函數。
多態的語句調用哪個類的成員函數是在運行時才能確定的,編譯時不能確定。因此,多態的函數調用語句被稱爲是“動態聯編”的,而普通的函數調用語句是“靜態聯編”的。
五、多態的作用
在面向對象的程序設計中,使用多態能夠增強程序的可擴充性,即程序需要修改或增加功能時,只需改動或增加較少的代碼。此外,使用多態也能起到精簡代碼的作用。
舉個簡單的例子:編寫一個幾何形體處理程序,輸入幾何形體的個數以及每個幾何形體的形狀和參數,要求按面積從小到大依次輸出每個幾何形體的種類及面積。假設幾何形體的總藪不超過 100 個。
針對這種問題,利用多態機制編寫,將幾何體的共同點抽象出來,如計算面積函數和顯示信息函數,形成一個基類。再針對不同形狀編寫其派生類。不僅簡化了大量工作,還有利於代碼後期維護。
具體的例子有很多,以後有時間再補充。