派生類物件的地址可以賦值給基礎類別指標。對於通過基礎類別指標呼叫基礎類別和派生類中都有的同名、同參數列的虛擬函式的語句,編譯時並不確定要執行的是基礎類別還是派生類的虛擬函式;而當程式執行到該語句時,如果基礎類別指標指向的是一個基礎類別物件,則基礎類別的虛擬函式被呼叫,如果基礎類別指標指向的是一個派生類物件,則派生類的虛擬函式被呼叫。這種機制就叫作“多型(polymorphism)”。
所謂“虛擬函式”,就是在宣告時前面加了 virtual 關鍵字的成員函數。virtual 關鍵字只在類定義中的成員函數宣告處使用,不能在類外部寫成員函數體時使用。靜態成員函數不能是虛擬函式。
包含虛擬函式的類稱為“多型類”。
多型可以簡單地理解為同一條函數呼叫語句能呼叫不同的函數;或者說,對不同物件傳送同一訊息,使得不同物件有各自不同的行為。
多型在物件導向的程式設計語言中如此重要,以至於有類和物件的概念,但是不支援多型的語言,只能被稱作“基於物件的程式設計語言”,而不能被稱為“物件導向的程式設計語言”。例如,Visual Basic 就是“基於物件的程式設計語言”。
下面是一個體現多型規則的例子。
#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;
}
程式的輸出結果是:
A::Print
B::Print
D::Print
E::Print
程式中,四個類之間的派生關係如下所示。