虚函数原理1
部分參考:http://blog.csdn.net/devilkin64/article/details/5939613
虛函數(shù)表的建立是取決于定義類的時候是否包含虛函數(shù),如果有類函數(shù)/ 方法聲明為虛,則改類會建立一張?zhí)摫?在網(wǎng)上找到一個牛人用匯編的方法論證虛 表是存放在常量區(qū)內(nèi)(具體論證就省略,否則就扯遠了). 繼承類會同樣建立一張?zhí)摫?并將覆蓋虛表中父類虛函數(shù)的地址. 在編譯階段,編譯器為每個包含虛函數(shù)的類創(chuàng)建一個虛表,這個類的所有對象中的虛表指針,都指向這同一份虛表;一般虛表指針放在對象的開始位置; 虛函數(shù)表是在代碼編譯生成,程序載入內(nèi)存的時候,放在內(nèi)存常量區(qū). 虛函數(shù)指針是在對象建立時由構(gòu)造函數(shù)生成并保存于對象地 址首部.虛函數(shù)指針:虛函數(shù)指針是在實例化對象 的時候由構(gòu)造函數(shù)生成的指向虛表的指針.放在對象地址的首位. 下面代碼用于顯 示虛表及虛表指針.class base { public: int a;virtual void Print(){cout<<"in base print\n";} };class d1:public base { public:void Print(){cout<<"in d1 print\n";}void d1Print(){cout<<"d1 self print \n";} };class d2:public d1 { public:void Print(){cout<<"in d2 print\n";}void d2Print(){cout<<"d2 self print \n";} };typedef void (*pfun)();int main() {base *md2 = new d2;md2->Print();d1 *md1 = new d2;md1->Print();//上面兩個例子說明,虛函數(shù)具有向下傳遞的特性;只要在最開始的基類中定義虛函數(shù),則其他所有的子孫類都默認是虛函數(shù)int *p2 =(int *) md2;//md2本來是指向?qū)ο蟮囊粋€指針,將此指針轉(zhuǎn)換為指向一個int數(shù)組的指針,這樣就能像訪問數(shù)組一樣訪問對象里面的數(shù)據(jù)cout<<*p2<<endl;//*p2是指放在對象md2中第一個位置的元素的值,這個值就是虛表的地址p2 =(int *)(*p2);//*p2是虛表的地址,也就是指虛表的指針,我們要把虛表也表示成數(shù)組的形式,把指向虛表的指針轉(zhuǎn)換為指向一個Int數(shù)組的指針printf("%x\n",p2);//cout<<p2<<endl;//printf("%d\n",p2);//上面三個輸出的值都是相等的,只不過是十進制或者十六進制表示的不同(pfun(*p2))();int *p1 = (int *) md1;cout<<*p1<<endl;//上面所有的輸出都是顯示的是類d2的虛表的地址,也就是說不管類有多少個對象,但是虛表只有一份/*int i =0;int *p = &i;cout<<&i<<" "<<p<<endl;*/delete md1;delete md2; }
總結(jié)