近日在學(xué)校bbs上與人討論C++的typeid關(guān)鍵字的實(shí)現(xiàn)問題,有人提到type_info的地址是存放在虛表的第一個(gè)位置上,頗覺得不妥,于是我在vc2003下實(shí)驗(yàn)了一番
在vc下,使用typeid的時(shí)候,如果typeid施加給的類型是沒有vptr的class或者根本不是class
那么匯編是
mov dword ptr [addr],offset A `RTTI Type Descriptor' (42AD40h)
也就是編譯器生成一個(gè)簡(jiǎn)單的type_info對(duì)象的表,并且在編譯期靜態(tài)決定下標(biāo),做一個(gè)簡(jiǎn)單查表操作。
如果typeid的操作對(duì)象是具有vptr的class,但是并不是一個(gè)引用或者指針的解引用形式,例如
A a;
typeid(a);
那么仍然僅僅會(huì)做查表操作
如果typeid的操作對(duì)象是具有vptr的class,并且是引用或者指針的解引用形式,例如
A * p = new A;
A & r = * p;
typeid( * p);
typeid(r);
那么就會(huì)調(diào)用一個(gè)叫___RTtypeid的函數(shù),并通過某種方法來獲取type_info對(duì)象
下面是___RTtypeid的反匯編,這里只列出關(guān)鍵的幾條指令
0041213E mov ecx,dword ptr [inptr] ;inptr是對(duì)象的地址
00412141 mov edx,dword ptr [ecx]
00412143 mov eax,dword ptr [edx - 4 ]
0041215F mov ecx,dword ptr [eax + 0Ch]
00412162 mov dword ptr [ebp - 48h],ecx
0041216C mov eax,dword ptr [ebp - 48h]
基本上等價(jià)于C語(yǔ)言的
int a1 = ( int )p; // p是對(duì)象的地址
int a2 = * ( int * )a1 - 4 ;
int a3 = * ( int * )a2 + 12 ;
int a4 = * ( int * )a3;
那么從這段代碼可以看出vc下type_info對(duì)象的存放位置[如下圖]
也就虛表下標(biāo)為-1的位置上存放了一個(gè)指向一個(gè)未知的表的指針(暫且將此表命名為runtime_info_table)
runtime_info_table的第4格上存放了type_info對(duì)象的地址
至于runtime_info_table里前3格上存放的是什么, 還需要再研究研究
一般來說它們?nèi)?, 但是對(duì)于多重虛繼承的類, 第二格上會(huì)是4, 可能和指針的偏移量有關(guān).
posted on 2006-10-26 10:46
shifan3 閱讀(3349)
評(píng)論(5) 編輯 收藏 引用 所屬分類:
C++