虚函数原理1
部分參考:http://blog.csdn.net/devilkin64/article/details/5939613
虛函數表的建立是取決于定義類的時候是否包含虛函數,如果有類函數/ 方法聲明為虛,則改類會建立一張虛表.在網上找到一個牛人用匯編的方法論證虛 表是存放在常量區內(具體論證就省略,否則就扯遠了). 繼承類會同樣建立一張虛表,并將覆蓋虛表中父類虛函數的地址. 在編譯階段,編譯器為每個包含虛函數的類創建一個虛表,這個類的所有對象中的虛表指針,都指向這同一份虛表;一般虛表指針放在對象的開始位置; 虛函數表是在代碼編譯生成,程序載入內存的時候,放在內存常量區. 虛函數指針是在對象建立時由構造函數生成并保存于對象地 址首部.虛函數指針:虛函數指針是在實例化對象 的時候由構造函數生成的指向虛表的指針.放在對象地址的首位. 下面代碼用于顯 示虛表及虛表指針.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();//上面兩個例子說明,虛函數具有向下傳遞的特性;只要在最開始的基類中定義虛函數,則其他所有的子孫類都默認是虛函數int *p2 =(int *) md2;//md2本來是指向對象的一個指針,將此指針轉換為指向一個int數組的指針,這樣就能像訪問數組一樣訪問對象里面的數據cout<<*p2<<endl;//*p2是指放在對象md2中第一個位置的元素的值,這個值就是虛表的地址p2 =(int *)(*p2);//*p2是虛表的地址,也就是指虛表的指針,我們要把虛表也表示成數組的形式,把指向虛表的指針轉換為指向一個Int數組的指針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; }
總結