多型的實現原理

2021-08-03 20:49:28 字數 2884 閱讀 7208

一、虛表

在c++語言中,每個有虛函式的類或者虛繼承的子類,編譯器都會為它生成乙個虛函式表(簡稱:虛表),表中的每乙個元素都指向乙個虛函式的位址。(注意:虛表是從屬於類的)

此外,編譯器會為包含虛函式的類加上乙個成員變數,是乙個指向該虛函式表的指標(常被稱為vptr),每乙個由此類別派生出來的類,都有這麼乙個vptr。虛表指標是從屬於物件的。也就是說,如果乙個類含有虛表,則該類的所有物件都會含有乙個虛表指標,並且該虛表指標指向同乙個虛表。

虛表的內容是依據類中的虛函式宣告次序--填入函式指標。派生類別會繼承基礎類別的虛表(以及所有其他可以繼承的成員),當我們在派生類中改寫虛函式時,虛表就受了影響;表中的元素所指的函式位址將不再是基類的函式位址,而是派生類的函式位址。

二、多型實現的原理(摘自網上)

下面,我將分別說明"無覆蓋"和"有覆蓋"時的虛函式表的樣子。沒有覆蓋父類的虛函式是毫無意義的。我之所以要講述沒有覆蓋的情況,主要目的是為了給乙個對比。在比較之下,我們可以更加清楚地知道其內部的具體實現。

一般繼承(無虛函式覆蓋)

下面,再讓我們來看看繼承時的虛函式表是什麼樣的。假設有如下所示的乙個繼承關係:

請注意,在這個繼承關係中,子類沒有過載任何父類的函式。那麼,在派生類的例項中,其虛函式表如下所示:

對於例項:derive d; 的虛函式表如下:

我們可以看到下面幾點:

1)虛函式按照其宣告順序放於表中。

2)父類的虛函式在子類的虛函式前面。

我相信聰明的你一定可以參考前面的那個程式,來編寫一段程式來驗證。

一般繼承(有虛函式覆蓋)覆蓋父類的虛函式是很顯然的事情,不然,虛函式就變得毫無意義。下面,我們來看一下,如果子類中有虛函式過載了父類的虛函式,會是乙個什麼樣子?假設,我們有下面這樣的乙個繼承關係。

為了讓大家看到被繼承過後的效果,在這個類的設計中,我只覆蓋了父類的乙個函式:f()。那麼,對於派生類的例項,其虛函式表會是下面的乙個樣子:

我們從表中可以看到下面幾點,

1)覆蓋的f()函式被放到了虛表中原來父類虛函式的位置。

2)沒有被覆蓋的函式依舊。

這樣,我們就可以看到對於下面這樣的程式,

base *b = new derive();

b->f();

由b所指的記憶體中的虛函式表的f()的位置已經被derive::f()函式位址所取代,於是在實際呼叫發生時,是derive::f()被呼叫了。這就實現了多型。

多重繼承(無虛函式覆蓋)

多重繼承(無虛函式覆蓋)

下面,再讓我們來看看多重繼承中的情況,假設有下面這樣乙個類的繼承關係。注意:子類並沒有覆蓋父類的函式。

對於子類例項中的虛函式表,是下面這個樣子:

我們可以看到:

1)  每個父類都有自己的虛表。

2)  子類的成員函式被放到了第乙個父類的表中。(所謂的第乙個父類是按照宣告順序來判斷的)

這樣做就是為了解決不同的父類型別的指標指向同乙個子類例項,而能夠呼叫到實際的函式。

多重繼承(含虛函式的覆蓋)

多重繼承(有虛函式覆蓋)

下面我們再來看看,如果發生虛函式覆蓋的情況。

下圖中,我們在子類中覆蓋了父類的f()函式。

下面是對於子類例項中的虛函式表的圖:

我們可以看見,三個父類虛函式表中的f()的位置被替換成了子類的函式指標。

三、過載、隱藏、覆蓋區別

過載:針對同一類,函式名字相同,引數列表不同,和返回值無關即返回值不能作為函式過載的判斷條件。

函式的兩個要素:引數與返回值。

如果同名函式的引數不同(包括型別、順序不同),那麼容易區別出它們是不同的函式。

如果同名函式僅僅是返回值型別不同,有時可以區分,有時卻不能。例如:

void function(void);

int function (void);

上述兩個函式,第乙個沒有返回值,第二個的返回值是int 型別。如果這樣呼叫函式:

int x = function ();

則可以判斷出function 是第二個函式。問題是在c++/c 程式中,我們可以忽略函式的返回值。在這種情況下,編譯器和程式設計師都不知道哪個function 函式被呼叫。

所以只能靠引數而不能靠返回值型別的不同來區分過載函式。編譯器根據引數為每個過載函式產生不同的內部識別符號。

隱藏:基於繼承,通過子類的物件 就無法調動父類的相同名字的函式(只要名字相同)

覆蓋:1子類繼承基類 2.父類有虛函式3.通過父類指標或者引用-----》通過介面實現多型。

多型 2 多型的實現原理

當類中宣告虛函式時,編譯器會在類中生成乙個虛函式表 虛函式表是乙個儲存類成員函式指標的資料結構 虛函式表是由編譯器自動生成與維護的 virtual成員函式會被編譯器放入虛函式表中 存在虛函式時,每個物件中都有乙個指向虛函式表的指標 vfptr指標 物件在建立的時,由編譯器對vfptr指標進行初始化 ...

多型實現的原理

多型實現的原理從兩個方面說明 1.虛函式表 2.rtti機制 當你在乙個類中使用了virtual關鍵字,那麼就產生了虛函式表,虛函式表中存放的是虛函式的入口位址,父類有父類的虛表,子類有子類的虛表,當繼承時,虛表進行了複製,在子類中重寫了父類的虛函式時,子類虛表中這個函式位址就替換成子類虛函式的位址...

多型實現原理

在繼承中構成多型有兩個條件 1 必須通過基類的指標或者引用呼叫虛函式 2 被呼叫的函式必須是虛函式,並且派生類必須對於虛函式進行重寫 這就是我們的多型,但是多型是怎麼實現的呢?class base private intm a int m b class a public base private ...