C 多型詳解

2021-07-31 22:02:31 字數 2976 閱讀 2080

前幾天在網上看到這樣的乙個問題:

多型現在一般的用法,就是拿乙個父類的指標去呼叫子類中被重寫的方法。但我搞不懂為什麼要那麼做,我們直接在子類中寫乙個同名的成員函式,從而隱藏父類的函式不就行了麼?

然後有人這樣回答:

將父模擬喻為電腦的外設介面,子模擬喻為外設,現在我有行動硬碟、u盤以及***,它們3個都是可以作為儲存但是也各不相同。如果我在寫驅動的時候,我用個父類表示外設介面,然後在子類中重寫父類那個讀取裝置的虛函式,那這樣電腦的外設介面只需要乙個。但如果我不是這樣做,而是用每個子類表示乙個外設介面,那麼我的電腦就必須有3個介面分別來讀取行動硬碟、u盤以及***。若以後我還有sd卡讀卡器,那我豈不是要將電腦拆了,焊個sd卡讀卡器的介面上去?

所以,用父類的指標指向子類,是為了面向介面程式設計。大家都遵循這個介面,弄成一樣的,到**都可以用,準確說就是「乙個介面,多種實現「。

這個解答很有意思!!!

忽然感覺學了很長時間的c++只是知道有多型這樣乙個重要的概念,程式設計時怎麼用,卻真的沒有仔細想一下它的機制,也就是它是怎麼實現的。於是看了些資料,做一下總結。

先看乙個例子:

執行完之後的結果是這樣的:

這個很好理解,但當我們將函式g()加上virtual之後再看結果會看到

變成了4。這是因為在後者中變成了虛函式了。

virtual是讓子類與父類之間的同名函式有聯絡,這就是多型性,實現動態繫結。

任何類若是有虛函式就會比比正常的類大一點,所有有virtual的類的物件裡面最頭上會自動加上乙個隱藏的,不讓我知道的指標,它指向一張表,這張表叫做vtable,vtable裡是所有virtual函式的位址。

下邊來看這樣兩段**:

1

class

shape ;

這個類的記憶體分布是這樣的:

就是在成員變數前有乙個vtable的指標,它會指向乙個table,這個table叫做虛函式表。

1

class ellipse : public

shape;

ellipse繼承與shape,看一下它的記憶體分布:

這裡的vtable不是物件的,而是屬於類的,這就是多型的實現機制。

這樣由上面的解釋我們來詳細講解一下多型的概念和實現:

多型(polymorphism)按字面的意思就是「多種狀態」。在物件導向語言中,介面的多種不同的實現方式即為多型。引用charlie calverts對多型的描述——多型性是允許你將父物件設定成為和乙個或更多的他的子物件相等的技術,賦值之後,父物件就可以根據當前賦值給它的子物件的特性以不同的方式運作。簡單的說,就是一句話:允許將子類型別的指標賦值給父類型別的指標。其實我看到過一句話:呼叫同名函式卻會因上下文的不同而有不同的實現。我覺得這樣更加貼切,還加入了多型三要素:(1)相同函式名  (2)依據上下文  (3)實現卻不同;

來看這個例子:

1 #include2

using

namespace

std;34

classa 7

virtual

void f() 89

inti;

10};

1112

class b : publica15

virtual

void f()

1617

intj;

18};

1920

intmain()

21

這時我們執行這個程式,b的f()函式會執行,執行結果是"b::f() 20",這裡就是多型中的動態繫結,本來是基型別的指標賦給了子型別的物件位址,這樣當執行時才能知道執行哪個f()函式。

之後修改main函式:

1

intmain()

2

執行結果是:

b::f() 20

a::f() 10

可見a.f()的結果輸出是不同的。有很多理由說明這個,其一就是通過指標或引用才是動態繫結,通過點運算是不可以的。

多型特性的工作依賴虛函式的定義,在需要解決多型問題的過載成員函式前,加上virtual關鍵字,那麼該成員函式就變成了虛函式,從上例**執行的結果看,系統成功的分辨出了物件的真實型別,成功的呼叫了各自的過載成員函式。

虛函式的定義要遵循以下重要規則:

1.如果虛函式在基類與派生類中出現,僅僅是名字相同,而形式引數不同,或者是返回型別不同,那麼即使加上了virtual關鍵字,也是不會進行滯後聯編的。 

2.只有類的成員函式才能說明為虛函式,因為虛函式僅適合用與有繼承關係的類物件,所以普通函式不能說明為虛函式。 

3.靜態成員函式不能是虛函式,因為靜態成員函式的特點是不受限制於某個物件。 

4.內聯(inline)函式不能是虛函式,因為內聯函式不能在執行中動態確定位置。即使虛函式在類的內部定義定義,但是在編譯的時候系統仍然將它看做是非內聯的。 

5.建構函式不能是虛函式,因為構造的時候,物件還是一片位定型的空間,只有構造完成後,物件才是具體類的例項。 

6.析構函式可以是虛函式,而且通常聲名為虛函式。

同時需要了解多型的特性的virtual修飾,不單單對基類和派生類的普通成員 函式有必要,而且對於基類和派生類的析構函式同樣重要!!!

C 多型詳解

c 程式語言是一款應用廣泛,支援多種程式設計的計算機程式語言。下面詳細介紹其中c 多型性的一些基本知識,以方便大家在學習過程中對此能夠有乙個充分的掌握。多型性可以簡單地概括為 乙個介面,多種方法 程式在執行時才決定呼叫的函式,它是物件導向程式設計領域的核心概念。多型 polymorphisn 字面意...

C 多型詳解

多型是物件導向的程式設計的關鍵技術。多型 呼叫同乙個函式名,可以根據需要但實現不同的功能。多型體現在兩個方面,我們以前學過的編譯時的多型性 函式過載 和現在我們這一章將要學習的執行時的多型性 虛函式 執行時多型 執行時的多型性是指在程式執行之前,根據函式名和引數無法確定應該呼叫哪乙個函式,必須在程式...

C 多型詳解

前幾天在網上看到這樣的乙個問題 多型現在一般的用法,就是拿乙個父類的指標去呼叫子類中被重寫的方法。但我搞不懂為什麼要那麼做,我們直接在子類中寫乙個同名的成員函式,從而隱藏父類的函式不就行了麼?然後有人這樣回答 將父模擬喻為電腦的外設介面,子模擬喻為外設,現在我有行動硬碟 u盤以及 它們3個都是可以作...