一種巧妙的取類的虛函式指標的方法

2021-06-04 12:21:30 字數 2505 閱讀 1970

熟悉c++開發的朋友們都知道,每乙個包含虛函式的類的物件的前四個位元組(32位系統中,以下例子都是在32位系統下)的記憶體中存放著該物件的虛函式表的指標。虛函式表中依次存放著該物件的每個虛函式的位址。

舉個例子:

class testa

;

testa::testa()

testa::~testa()

void testa::testafunc()

void testa::testafunc1()

int main()

對於testa這個類的物件a來說,它在記憶體中的布局如下:

我們可以採用取記憶體的方法來獲得某乙個虛函式的指標,方法如下:

typedef  void(*func) (void);

在main函式中加入以下**:

func pfunc = null;

pfunc = (func)*((int *)(*(int*)(&a)) + 0);

pfunc();                    //實際呼叫的是testafunc()

pfunc = (func)*((int *)(*(int*)(&a)) + 1);

pfunc();                    //實際呼叫的是testafunc1()

輸出為:

testafunc is called!

testafunc1 is called!

但是通過記憶體來取虛函式指標的方法有點繁瑣,稍微乙個不留神忘了指標轉換或者解除引用就會導致錯誤,這裡,我給大家介紹一種清晰簡單的方法來取虛函式。

如上圖所示,虛函式表其實是一塊連續的記憶體,裡面每個元素(每四個位元組)都是乙個函式指標,這樣的話,我們完全可以把它看做乙個結構體,該結構體的每個成員是乙個函式指標。

struct testa_vtpr

;

如此這樣的話,我們完全可以用以下方式來引用testa 類的虛函式

(將以下**加入main函式)

testa a;

testa_vtpr **pvtable = (testa_vtpr**)(void*)&a;

testa_vtpr *pvtpr = *pvtable;

pvtpr->hook(&a);

pvtpr->hook1(&a);

(&a)->testafunc();  //必須用指向a物件的指標來引用testafunc,否則不會去查詢虛表

(&a)->testafunc1(); //同上

程式輸出如下:

testafunc is called!

testafunc1 is called!

testafunc is called!

testafunc1 is called!

可以看到pvtpr->hook(&a); 和 (&a)->testafunc();執行的結果一樣的。

親們,你們明白了麼?

虛函式的一種替代方案

虛函式的目的是實現物件的動態繫結,但是有些情況下,可能換一種替代方案,可能會使類的設計更加穩定,易用,下面列出乙個我認為很棒的虛函式的替代方案。使用non virtual inte ce nvi 手法,它以public non virtual 成員函式包裹較低訪問性的virtual函式 class ...

一種「標準」的虛函式機制簡介

編譯器是如何針對 虛函式產生可以再執行時刻確定被呼叫函式的 呢?也就是說,虛函式實際上是如何被編譯器處理的呢?lippman在深度探索c 物件模型中的不同章節講到了幾種方式,這裡把 標準的 方式簡單介紹一下。我所說的 標準 方式,也就是所謂的 vtable 機制。編譯器發現乙個類中有被宣告為virt...

一種巧妙的記憶體池演算法 HeapBlock

在乙個簡單的gui庫中看到的演算法,非常巧妙,適用於需要頻繁分配和釋放相同大小資料塊的情況,如gui庫中的視窗結構,socket結構等,演算法額外開支極小。cpp view plain copy print?typedef dword hblockheap typedef unsigned char...