C 多型總結

2021-09-29 03:58:26 字數 3458 閱讀 6551

在問題引出(賦值相容性原則遇上函式重寫)在上節中我們說明了c++的繼承的時候,說明c++的繼承型別相容性原則:

子類物件可以當作父類物件使用

子類物件可以直接賦值給父類物件

子類物件可以直接初始化父類物件

父類指標可以直接指向子類物件

父類引用可以直接引用子類物件

但是如果子類定義了與父類中原型相同的函式會發生什麼?

函式重寫的概念

在子類中定義與父類中原型相同的函式,函式重寫只發生在父類與子類之間。

引入乙個**進行分析:

#include

using namespace std;

class parent};

class child : public parent};

void

test1

(parent *p)

void

test1

(parent& p)

intmain()

測試結果如下:

測試結果表示在子類對父類進行函式重寫後,賦值相容性原則遇上函式重寫。對於重寫的函式都是執行父類的成員函式。這一點並不是我們所希望的,我們更希望編譯器可以根據實際呼叫的物件來判斷重寫函式的呼叫。這一點就導致多型的機制的誕生,這個也是程式設計當中我們對於面對物件所提出新的需求----編譯器可以根據物件的不同來執行不同的重寫函式。

物件導向新需求:

還是上文相同的測試**

#include

using namespace std;

class parent};

class child : public parent};

void

test1

(parent *p)

void

test1

(parent& p)

intmain()

我們先舉乙個戰機pk的**來說明多型使用的優勢:

#include

using

namespace std;

#include

"iostream"

using

namespace std;

class

herofighter

// 英雄戰機};

class

advherofighter

:public herofighter // 英雄戰機2 };

class

enemyfighter

// 敵方戰機 };

void

objpk

(herofighter* hf, enemyfighter* enemyf)

else

}int

main()

這個**中有兩個英雄戰機,一種是herofighter父類,一種是進化的英雄戰機advherofighter子類重寫了父類herofighter中的返回戰鬥力的函式。函式用virtual表示這個函式是多型的。這樣我們寫得obpk便可以通過物件的不同,來應用重名的不同函式,這樣好處不言而喻。回到面對物件的模型來講,面對物件有三個重要的特點封裝,繼承,多型。

封裝:突破了c語言函式的限制。

繼承:提高了**復用,也提高了程式設計的效率

多型:多型多型可以使用未來,80年**了乙個框架,90年寫的**可以應用於這個框架。 多型是軟體行業追尋的乙個目標,正如我們這個戰機的案例,我們可以寫3代戰機,4代戰機,n代戰機。他們的戰鬥力不同,但是我們可以通過通重寫函式並讓其多型,來實現功能。

多型成立的三個條件:

要有繼承

要有函式重寫

c 虛函式 要有父類指標(父類引用)指向子類物件

多型是設計模式的基礎,多型是框架的基礎理論知識:

1 多型的實現原理

下面我們通過幾張圖圖來闡述一下多型的實現原理:

當類中宣告虛函式時,編譯器會在類中生成乙個虛函式表

虛函式表是乙個儲存類成員函式指標的資料結構

虛函式表是由編譯器自動生成與維護的

virtual成員函式會被編譯器放入虛函式表中 存在虛函式時,每個物件中都有乙個指向虛函式表的指標(vptr指標)

說明1:

通過虛函式表指標vptr呼叫重寫函式是在程式執行時進行的,因此需要通過定址操作才能確定真正應該呼叫的函式。而普通成員函式是在編譯時就確定了呼叫的函式。在效率上,虛函式的效率要低很多。

說明2:

出於效率考慮,沒有必要將所有成員函式都宣告為虛函式

證明vptr指標的存在

在這裡插入**片#include 

using

namespace std;

class

aprivate

:int a;};

class

bint a;};

intmain()

輸出結果:

顯然類b創立的物件b1比類a建立的物件新增乙個vptr指標變數(4個位元組)。

3 建構函式中能呼叫虛函式,實現多型嗎

物件中的vptr指標什麼時候被初始化?

物件在建立的時,由編譯器對vptr指標進行初始化

只有當物件的構造完全結束後vptr的指向才最終確定

父類物件的vptr指向父類虛函式表

子類物件的vptr指向子類虛函式表

#include

using

namespace std;

class

apublic

:virtual

void

print()

};classb:

public a

public

:virtual

void

print()

};intmain()

在vptr指標的初始化過程中,vtr指標先是指向父類的虛函式表,在父類函式初始化後,在指向子類的虛函式表。換句話說vptr指標的初始化是分步的,如圖所示。

c 多型總結

多型 多型可以簡單地概括為 乙個介面,多種方法 程式在執行時才決定呼叫的函式,它是物件導向程式設計領域的核心概念。接下來,我寫乙個簡單地函式來說明多型 includeusing namespace std int add int left,int right float add float left...

C 多型總結

多型繫結分兩種情況,一種是靜態繫結即編譯時多型,一種是動態繫結即執行時多型是利用過載實現的。對於非虛函式的成員來說,系統在編譯時,按照函式的引數的區別來繫結要實現的操作,在編譯時就確定了呼叫哪個函式。簡單地說,虛函式是動態繫結的基礎 動態繫結是實現執行時多型的基礎。要觸發動態繫結,需滿足兩個條件 1...

C 多型總結

多型概念 同乙個事物在不同環境下具有不同的狀態 虛函式概念 在函式返回值前加上 virtual 關鍵字 多型分類 靜態多型 早繫結 在編譯器編輯時確認要呼叫的函式 1 函式過載 2 泛型程式設計 動態多型 晚繫結 在程式執行時確認將要呼叫的函式 1 基類中存在虛函式 2 繼承當中對基類進行重寫並且 ...