C 虛函式與虛函式表

2021-05-04 21:28:34 字數 2033 閱讀 6161

概念:

虛函式(virtual function)是通過一張虛函式表(virtual table)來實現的,簡稱為v-table。

學習虛函式的作用:理解

c++實現多型的機制、

解決了繼承、覆蓋的問題。

以下摘抄自:http://www.cppblog.com/xczhang/archive/2008/01/20/41508.html

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

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

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

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

我們可以看到:

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

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

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

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

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

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

我們可以看見,三個父類虛函式表中的f()的位置被替換成了子類的函式指標。這樣,我們就可以任一靜態型別的父類來指向子類,並呼叫子類的f()了。如:

derive d;

base1 *b1 = &d;

base2 *b2 = &d;

base3 *b3 = &d;

b1->f(); //derive::f()

b2->f(); //derive::f()

b3->f(); //derive::f()

b1->g(); //base1::g()

b2->g(); //base2::g()

b3->g(); //base3::g()

每次寫c++的文章,總免不了要批判一下c++。這篇文章也不例外。通過上面的講述,相信我們對虛函式表有乙個比較細緻的了解了。水可載舟,亦可覆舟。下面,讓我們來看看我們可以用虛函式表來幹點什麼壞事吧。

一、通過父型別的指標訪問子類自己的虛函式

我們知道,子類沒有過載父類的虛函式是一件毫無意義的事情。因為多型也是要基於函式過載的。雖然在上面的圖中我們可以看到base1的虛表中有derive的虛函式,但我們根本不可能使用下面的語句來呼叫子類的自有虛函式:

base1 *b1 = new derive();

b1->f1(); //編譯出錯

任何妄圖使用父類指標想呼叫子類中的未覆蓋父類的成員函式的行為都會被編譯器視為非法,所以,這樣的程式根本無法編譯通過。但在執行時,我們可以通過指標的方式訪問虛函式表來達到違反c++語義的行為。(關於這方面的嘗試,通過閱讀後面附錄的**,相信你可以做到這一點)

二、訪問non-public的虛函式

另外,如果父類的虛函式是private或是protected的,但這些非public的虛函式同樣會存在於虛函式表中,所以,我們同樣可以使用訪問虛函式表的方式來訪問這些non-public的虛函式,這是很容易做到的。

如: class base

class derive : public base{

typedef void(*fun)(void);

void main() {

derive d;

fun pfun = (fun)*((int*)*(int*)(&d)+0);

pfun();

C 虛函式與虛函式表

多型性可分為兩類 靜態多型和動態多型。函式過載和運算子過載實現的多型屬於靜態多型,動態多型性是通過虛函式實現的。每個含有虛函式的類有一張虛函式表 vtbl 表中每一項是乙個虛函式的位址,也就是說,虛函式表的每一項是乙個虛函式的指標。沒有虛函式的c 類,是不會有虛函式表的。兩張圖 簡單例子 1 inc...

C 虛函式與虛函式表

1 多型是c 三大特性之一,也是物件導向設計中乙個非常重要的概念。所謂多型性就是當 不同的物件接收到相同的訊息時所產生的不同的響應。c 中虛函式的存在其實就是為了解決物件導向程式設計設計當中的多型問題,即通過基類的指標 或者是引用 指向例項化 的派生類物件,從而通過基類的指標 或者是引用 呼叫派生類...

虛函式與虛函式表

當類中有虛函式時,類的大小會多4個位元組 多出的這4個位元組是乙個位址,指向一張表,裡面儲存了所有虛函式的位址 虛函式表 class base virtual void function 2 virtual void function 3 class sub public base virtual ...