1. 程式人生 > 實用技巧 >C++面向物件入門(三十一)初步認識多型

C++面向物件入門(三十一)初步認識多型

繼承描述的是類與類之間的層次關係, 而多型則描述的是這種繼承關係以及類自生特定成員函式之間的關係來解決行為的再抽象問題
多型性的兩種表現形式:
1 不同物件在收到相同資訊時, 產生不同的動作, 主要通過虛擬函式來實現
2 同一物件在收到相同資訊時卻產生不同的函式呼叫, 主要通過函式過載來實現 多型性就是同一符號或名字在不同情況下具有不同解釋的現象, 即指同一函式的多種形態
C++支援兩種多型性:
1 編譯時的多型性
2 執行時的多型性 函式聯編: 函式呼叫在編譯時或在執行時確定其連結上相應函式體的程式碼的過程 C++的兩種聯編方式
1 靜態聯編: 在程式編譯連線階段進行的聯編. 編譯器根據原始碼呼叫固定的的函式識別符號, 然後由聯結器接管
這些識別符號, 並利用實體地址代替, 又稱為早期聯編, 在程式執行之前完成的. 該聯編方式支援的多型性被稱作
編譯時的多型性 ,呼叫過載函式時, 編譯器可以根據呼叫時所使用的實參在編譯時就確定應呼叫哪個函式. 靜態聯編優點: 速度快, 開銷小(傳遞引數, 指向函式呼叫, 清除棧等) 2 動態聯編: 程式在執行時進行的聯編, 只有向具有多型性的函式傳遞一個實際物件時,該函式才有可能與多種
可能的函式中的一種聯絡起來. 這種聯編又稱為晚期聯編. 動態聯編支援的多型性被稱為執行時的多型性. 動態聯編的優點: 增加了程式設計靈活性, 問題抽象性和程式易維護性.
動態聯編的確定: 函式呼叫速度慢(相比於靜態聯編) 使用virtual關鍵字指明某個成員函式具有多型性並且使用動態聯編, 此時稱該函式為虛擬函式
語法:
virtual 返回值型別 函式名(引數列表)
{
函式體
} 程式碼示例:
#include<iostream>
using namespace std;

/*
繼承描述的是類與類之間的層次關係, 而多型則描述的是這種繼承關係以及類自生特定成員函式之間的關係來解決行為的再抽象問題
多型性的兩種表現形式:
1 不同物件在收到相同資訊時, 產生不同的動作, 主要通過虛擬函式來實現
2 同一物件在收到相同資訊時卻產生不同的函式呼叫, 主要通過函式過載來實現

多型性就是同一符號或名字在不同情況下具有不同解釋的現象, 即指同一函式的多種形態
C++支援兩種多型性:
1 編譯時的多型性
2 執行時的多型性

函式聯編: 函式呼叫在編譯時或在執行時確定其連結上相應函式體的程式碼的過程

C++的兩種聯編方式
1 靜態聯編: 在程式編譯連線階段進行的聯編. 編譯器根據原始碼呼叫固定的的函式識別符號, 然後由聯結器接管
這些識別符號, 並利用實體地址代替, 又稱為早期聯編, 在程式執行之前完成的. 該聯編方式支援的多型性被稱作
編譯時的多型性 ,呼叫過載函式時, 編譯器可以根據呼叫時所使用的實參在編譯時就確定應呼叫哪個函式.

靜態聯編優點: 速度快, 開銷小(傳遞引數, 指向函式呼叫, 清除棧等)

2 動態聯編: 程式在執行時進行的聯編, 只有向具有多型性的函式傳遞一個實際物件時,該函式才有可能與多種
可能的函式中的一種聯絡起來. 這種聯編又稱為晚期聯編. 動態聯編支援的多型性被稱為執行時的多型性.

動態聯編的優點: 增加了程式設計靈活性, 問題抽象性和程式易維護性.
動態聯編的確定: 函式呼叫速度慢(相比於靜態聯編)

使用virtual關鍵字指明某個成員函式具有多型性並且使用動態聯編, 此時稱該函式為虛擬函式
語法:
virtual 返回值型別 函式名(引數列表)
{
    函式體
}
*/ class A48 { public : int a; int b; A48(); void aMultiplyB(); virtual void aAddB(); }; class B48 : public A48 { public : int a; int b; B48(); void aMultiplyB(); void aAddB(); }; void func1(A48 a) { cout << "object param:"; a.aMultiplyB(); } void func1(A48 &a, int) { cout << "reference param:"; a.aMultiplyB(); } void func1(A48*a) { cout << "pointer param:"; a->aMultiplyB(); } void func2(A48 a) { cout << "object param:"; a.aAddB(); } void func2(A48 &a, int) { cout << "reference param:"; a.aAddB(); } void func2(A48 *a) { cout << "pointer param:"; a->aAddB(); } int main() { A48 a; B48 b; func1(a); //當呼叫普通成員函式時, 無論傳入的引數是物件, 引用還是指標型別, 據呼叫的是基類的成員函式 //傳入B48物件給函式func1(A48), 仍呼叫的是A48的aMultiplyB()方法,需要使用繼承時的多型性來解決 func1(b); //傳入B48物件的引用 func1(b, 0); //傳入B48物件的指標 func1(&b); func2(a); //當呼叫的函式是一個虛擬函式時, 傳入物件型別引數, 呼叫基類方法, 傳入引用型別引數和指標型別引數, 呼叫自己的方法 //傳入B48物件給函式func2(A48), 仍呼叫的是A48的aAddB()方法,需要使用繼承時的多型性來解決 func2(b); //傳入B48物件的引用, 呼叫的是B48的aAddB() func2(b,0); //傳入B48物件的指標, 呼叫的是B48的aAddB() func2(&b); b.aAddB(); system("pause"); } A48::A48() :a(3), b(4) { } void A48::aAddB() { cout << "A48a + b = " << a + b << endl; } void A48::aMultiplyB() { cout << "A48 a * b = " << a * b << endl; } B48::B48():A48(),a(4),b(5) { } void B48::aMultiplyB() { cout << "B48 a * b = " << a * b << endl; } void B48::aAddB() { cout << "B48 a + b = " << a + b << endl; }