虛函式 從零開始 2

2021-06-03 08:03:09 字數 1782 閱讀 3394

三, 以一段**開始

#include

using namespacestd;

classa; //end//虛函式示例**2

intmain(){

void(a::*fun)(); //定義乙個函式指標

a *p=newb;

fun=&a::fun;

(p->*fun)();

fun = &a::fun2;

(p->*fun)();

deletep;

system(「pause」);

你能估算出輸出結果嗎?如果你估算出的結果是a::fun和a::fun2,呵呵,恭喜恭喜,你中圈套了。其實真正的結果是b::fun和b::fun2,如果你想不通就接著往下看。給個提示,&a::fun和&a::fun2是真正獲得了虛函式的位址嗎?

首先我們回到第二部分,通過段實作**,得到乙個「通用」的獲得虛函式位址的方法

#include

using namespacestd;

//將上面「虛函式示例**2」新增在這裡

voidcallvirtualfun(void* pthis,intindex=0){

void(*funptr)(void*);

longlvptraddr;

memcpy(&lvptraddr,pthis,4);

memcpy(&funptr,reinterpret_cast<long*>(lvptraddr)+index,4);

funptr(pthis); //呼叫

intmain(){

a* p=newb;

callvirtualfun(p); //呼叫虛函式p->fun()

callvirtualfun(p,1);//呼叫虛函式p->fun2()

system(「pause」);

現在我們擁有乙個「通用」的callvirtualfun方法。

這個通用方法和第三部分開始處的**有何聯絡呢?聯絡很大。由於a::fun()和a::fun2()是虛函式,所以&a::fun和&a::fun2獲得的不是函式的位址,而是一段間接獲得虛函式位址的一段**的位址,我們形象地把這段**看作那段callvirtualfun。編譯器在編譯時,會提供類似於callvirtualfun這樣的**,當你呼叫虛函式時,其實就是先呼叫的那段類似callvirtualfun的**,通過這段**,獲得虛函式位址後,最後呼叫虛函式,這樣就真正保證了多型性。同時大家都說虛函式的效率低,其原因就是,在呼叫虛函式之前,還呼叫了獲得虛函式位址的**。

最後的說明:本文的**可以用vc6和dev-c++4.9.8.0通過編譯,且執行無問題。其他的編譯器小弟不敢保證。其中,裡面的模擬方法只能看成模型,因為不同的編譯器的低層實現是不同的。例如this指標,dev-c++的gcc就是通過壓棧,當作引數傳遞,而vc的編譯器則通過取出位址儲存在ecx中。所以這些模擬方法不能當作具體實現。

ps:小弟水平實在有限,不管是技術上的,還是語文上的,如果文中有什麼問題,歡迎個位大蝦和菜鳥朋友指出。閃了~~

從零開始學編碼2

從零開始學編碼1 接著上次說,計算機內的世界是由0和1組成的。很多種事物可以表現成0和1。例如 女人是0,男人是1。手電筒滅是0,亮是1。這次我們就說一說手電筒。小時候上夜自習,農村的晚上沒有路燈,學完冰心奶奶的小橘燈後,我們熱衷於用酒盒子做燈籠,夜自習放學挑著燈籠走。後來見有人拿小手電筒,還帶彩光...

從零開始學Python 函式

對於任何語言來說,函式都是必不可少的部分,對於python一樣如此。python中有非常多的內建函式,比如 求絕對值函式abs 求長度函式len 求總和函式sum 輸出字元函式input 等等,大家可以去官方 看一下官方文件,這裡我們就不再贅述了。我們來看一下在python中如何自定義函式和函式中的...

Django 從零開始

方法1 pip install django 1.6.5 測試是否安裝成功 python import django 1,6,5,final 0 django 使用了 python 標準的 distutils 安裝法,在 linux 平台可能包括如下步驟 tar xzvf django tar.gz...