c 之 多型性

2021-09-07 09:43:14 字數 4204 閱讀 8967

先看乙個例子:

然後我們引進多型,看看**公升級的威力;

1 #include2

using

namespace

std;34

class

liberation

10virtual

intcombat()

1114

private:15

intcapability;

16};

17class liberation_adv :public

liberation

1824

int combat() override //派生類重寫的函式不用加virtual也是virtual的,建議加上,方便後續繼承這個類的文件閱讀,c++11增加關鍵字

//override告訴編譯器和讀者,這是個被重寫的函式

2528

private:29

intcapability;

30};

3132

class

enemy

38int

combat()

3942

private:43

intcapability;

44};

4546

void play(liberation &l, enemy &e)

4753}54

intmain()

55

用多型的好處:呼叫乙個函式,簡化**結構,關鍵在於可維護性好。如果現在我又派生了乙個類l3,只用呼叫函式的介面,就可以僅僅增加乙個類定義的情況下,完成專案的維護。

實現多型三要素:

1、要有public繼承;

2、要有虛函式重寫;

3、要有基類的指標或者引用繫結到派生類。

滿足上訴要求,可以實現動態聯編(執行時型別才可知),否則是靜態聯編(編譯時型別就已知)。

c++中的多型(polymorphism)是指由繼承而產生的相關的不同的類, 其物件對

同一訊息會作出不同的響應。

多型性是物件導向程式設計的乙個重要特徵, 能增加程式的靈活性。 可以減

輕系統公升級, 維護, 除錯的工作量和複雜度。

多型是一種不同層次分類下的重要聯絡, 是一種跨層操作。

多型實現的前提

賦值相容規則是指在需要基類物件的任何地方都可以使用公有派生類的物件來替代。

賦值相容是一種預設行為, 不需要任何的顯式的轉化步驟, 只能發生在

public

繼承(其他private和protected繼承,多型無意義,因為不能在類外訪問屬性或方法了)方式中, 是多型實現的前提條件。

賦值相容規則中所指的替代包括以下的情況:

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

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

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

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

當使用父類指標(引用) 指向子物件時, 子類物件退化為父類物件, 只能訪問父類中定義的成員 

父類也可以通過強轉的方式轉化為子類, 但存在訪問越界的風險。

子類中可以重定義父類中已經存在的成員函式, 即函式重寫。

當函式重寫遇到賦值相容時, 編譯器只能根據指標的型別判斷所指向的對

象, 根據賦值相容原則, 編譯器認為父類指標指向的是父類物件, 只能呼叫父類

中定義的同名函式。

物件導向程式設計中, 通常需要根據實際的物件型別判斷如何呼叫重寫函式。 當

父類指標指向父類物件, 則呼叫父類定義的函式; 當父類指標指向的是子類物件

時, 需要呼叫子類定義的函式; 當父類引用對父類物件進行引用時, 呼叫父類對

象定義的函式; 當父類引用對子類物件進行引用時, 呼叫子類定義的函式。

c++通過 virtual 關鍵字對多型進行支援, 被 virtual 宣告的函式被重寫後具有多型屬性。 

虛函式的宣告語法如下:

virtual 函式宣告;

虛函式的使用規則如下:

a、 在父類中用 virtual 宣告成員函式為虛函式。 類外實現虛函式時, 不能再加 virtual。

b、 在派生類中重定義父類中已經存在的成員函式稱為函式覆寫, 要求函式名,

返值型別, 函式引數個數及型別全部匹配, 並根據派生類的需要重新定義函式體。

c、 當乙個成員函式被宣告為虛函式後, 其派生類中完全相同的函式也為虛函

數, 派生類中的虛函式可以加 virtual 關鍵字, 也可以不加,建議都加上,為了**擴充套件和閱讀(如果不寫virtual(雖然不寫也是virtual的),

之後有乙個類繼承這個派生類,只看這個派生類的宣告,不能一眼就看出這個派生類重寫了該派生類的直接或者間接父類的函式)。

d、 定義乙個父類物件指標, 使其指向其子類的物件, 通過父類指標呼叫虛函

數, 此時呼叫的是子類的同名函式,引用同理。

e、 建構函式不能為虛函式, 在建構函式執行完畢後虛函式表指標才能被正

確初始化。 析構函式可以為虛函式,一般來說需要將析構函式宣告為虛函式。 建構函式執行時, 虛函式表指

針未被正確初始化, 因此建構函式不可能發生多型; 析構函式函式執行時, 虛函

數表指標已經被銷毀, 因此析構函式也不可能發生多型。 建構函式和析構函式中

只能呼叫當前類中定義的函式版本。

純虛函式的宣告語法如下:

virtual 函式宣告 = 0;

純虛函式的使用規則如下:

a、 含有純虛函式的類, 稱為抽象基類, 不可例項化, 即不能建立物件, 存在

的意義就是被繼承, 提供類族的公共介面。

b、 純虛函式只有宣告, 沒有實現。

c、 如果乙個類中宣告了純虛函式, 而在派生類中沒有對純虛函式進行實現,

則該虛函式在派生類中仍然為純虛函式, 派生類仍然為抽象基類。

虛函式的使用規則如下:

a、 只有類的成員函式才能宣告為虛函式。 虛函式僅適用於有繼承關係的類對

象, 所以普通函式不能宣告為虛函式。

b、 靜態成員函式不能是虛函式。 靜態成員函式不受物件的**, 只有類的資訊。

c、 內聯函式不能是虛函式。

d、 建構函式不能是虛函式。 構造時, 物件的建立尚未完成。 構造完成後, 才能算乙個名符其實的物件。

e、 析構函式可以是虛函式且通常宣告為虛函式

f、 含有虛函式的類, 析構函式也必須宣告為虛函式。 在 delete 父類指標的時候, 會呼叫子類的析構函式。

多型的意義如下:

a、 在程式執行過程中展現出的動態特性

b、 函式重寫必須多型實現, 否則沒有意義

c、 多型是物件導向元件化程式設計的基礎特性

d、 多型是一種跨層操作

靜態聯編是在程式的編譯期間就能確定具體的函式呼叫, 如函式過載。

動態聯編是在程式實際執行時才能確定具體的函式呼叫, 如virtual函式重寫。

虛函式是為了實現動態多型, 是當程式執行到虛函式時才會從虛函式表裡找

實際執行的虛函式; 而函式過載實現的是靜態多型, 是在程式編譯時就能找到

函式位址。

C 學習之多型性

類的幾個重要特性之一多型性,有著廣泛的用途。類的多型性包括 編譯時多型和執行時多型。編譯時多型表現為乙個同名的方法會根據引數型別 個數和位置的不同有不同執行效果。通過方法過載來實現。顧名思義,它由編譯器根據呼叫引數的不同,選擇相應的函式。執行時多型通過虛方法實現。表現為 相同的引數,仍會執行不同的函...

C 之多型性1

過載 類中定義的方法可能有不同的版本 public bool withdraw double amt,string name public bool withdraw double amt 特點 兩必須一可以 方法名必須相同 引數類標必須不相同 返回值型別可以不相同 虛函式 宣告虛方法 使用virt...

C 特性之多型性

c 多型性概括為 乙個介面,多種方法 程式在執行時才決定呼叫的函式,它是物件導向程式設計領域的核心概念。c 多型性是通過虛函式來實現的,虛函式允許子類重新定義成員函式,而子類重新定義父類的做法成為覆蓋或者重寫,重寫可以有兩種,直接重寫成員函式和重寫虛函式,只有重寫了虛函式的才能算作體現了c 多型性 ...