C 虛函式表解析

2022-08-30 19:57:14 字數 3341 閱讀 8802

這篇部落格「比較深度介紹了虛函式表解析。

c++中的虛函式的作用主要是實現了多型的機制。關於多型,簡而言之就是用父型別別的指標指向其子類的例項,然後通過父類的指標呼叫實際子類的成員函式。這種技術可以讓父類的指標有「多種形態」,這是一種泛型技術。所謂泛型技術,說白了就是試圖使用不變的**來實現可變的演算法。比如:模板技術,

rtti

技術,虛函式技術,要麼是試圖做到在編譯時決議,要麼試圖做到執行時決議。

對c++ 了解的人都應該知道虛函式(virtual function)是通過一張虛函式表(virtual table)來實現的。簡稱為v-table。在這個表中,主是要乙個類的虛函式的位址表,這張表解決了繼承、覆蓋的問題,保證其容真實反應實際的函式。這樣,在有虛函式的類的例項中這個表被分配在了這個例項的記憶體中,所以,當我們用父類的指標來操作乙個子類的時候,這張虛函式表就顯得由為重要了,它就像乙個地圖一樣,指明了實際所應該呼叫的函式。

這裡我們著重看一下這張虛函式表。c++的編譯器應該是保證虛函式表的指標存在於物件例項中最前面的位置(這是為了保證取到虛函式表的有最高的效能——如果有多層繼承或是多重繼承的情況下)。這意味著我們通過物件例項的位址得到這張虛函式表,然後就可以遍歷其中函式指標,並呼叫相應的函式。

我們可以看到下面幾點:

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

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

我們可以看到:

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

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

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

二、訪問non-public的虛函式

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

如:class base

class derive : public base

virtual

void g()

virtual

void h() };

class

base2

virtual

void g()

virtual

void h() };

class

base3

virtual

void g()

virtual

void h() };

class derive : public base1, public base2, public

base3

virtual

void g1() };

typedef

void(*fun)(void);

intmain()

先更改目錄到c++程式所在專案的目錄。

用cl /d1 reportallclasslayout "vitual table.cpp"  或 cl /d1 reportsingleclasslayout*** "vitual table.cpp"(***可以是base1,base2,base3,derived)來列印***類的記憶體布局和虛函式表。

命令提示 視窗 摘要

d:\program files (x86)\microsoft visual studio 10.0\vc\include\xlocale(323) : wa

rning c4530: 使用了 c++ 異常處理程式,但未啟用展開語義。請指定 /ehsc

class base2 size(8):

+---

0 |

+---

base2::$vftable@:

| &base2_meta

| 0

0 | &base2::f

1 | &base2::g

2 | &base2::h

base2::f this adjustor: 0

base2::g this adjustor: 0

base2::h this adjustor: 0

f:\visual studio 2010\projects\vitual table>cl /d1 reportsingleclasslayoutderive

"vitual table\vitual table.cpp"

用於 x64 的 microsoft (r) c/c++ 優化編譯器 16.00.30319.01 版

vitual table.cpp

d:\program files (x86)\microsoft visual studio 10.0\vc\include\xlocale(323) : wa

rning c4530: 使用了 c++ 異常處理程式,但未啟用展開語義。請指定 /ehsc

class derive size(24):

+---

| +--- (base class base1)

0 | |

| +---

| +--- (base class base2)

8 | |

| +---

| +--- (base class base3)

16 | |

| +---

+---

derive::$vftable@base1@:

| &derive_meta

| 0

0 | &derive::f      //derived的vptr 指標與 base1的vptr指標指向同乙個位址空間。即$vftable@base1@和base1的vftable 是同乙個位址空間。

1 | &base1::g

2 | &base1::h

3 | &derive::g1

derive::$vftable@base2@:

| -8

0 | &thunk: this-=8; goto derive::f

1 | &base2::g

2 | &base2::h

derive::$vftable@base3@:

| -16

0 | &thunk: this-=16; goto derive::f

1 | &base3::g

2 | &base3::h

derive::f this adjustor: 0

derive::g1 this adjustor: 0

C 虛函式表解析

前言 c 中的虛函式的作用主要是實現了多型的機制。關於多型,簡而言之就是用父型別別的指標指向其子類的例項,然後通過父類的指標呼叫實際子類的成員函式。這種技術可以讓父類的指標有 多種形態 這是一種泛型技術。所謂泛型技術,說白了就是試圖使用不變的 來實現可變的演算法。比如 模板技術,rtti技術,虛函式...

C 虛函式表解析

c 中的虛函式的作用主要是實現了多型的機制。關於多型,簡而言之就是用父型別別的指標指向其子類的例項,然後通過父類的指標呼叫實際子類的成員函式。這種技術可以讓父類的指標有 多種形態 這是一種泛型技術。所謂泛型技術,說白了就是試圖使用不變的 來實現可變的演算法。比如 模板技術,rtti技術,虛函式技術,...

C 虛函式表解析

今天我做的筆記 c 中的虛函式的作用主要是實現了多型的機制。關於多型,簡而言之就是用父型別別的指標指向其子類的例項,然後通過父類的指標呼叫實際子類的成員函式。這種技術可以讓父類的指標有 多種形態 這是一種泛型技術。所謂泛型技術,說白了就是試圖使用不變的 來實現可變的演算法。比如 模板技術,rtti技...