近日在学校bbs上与人讨论C++的typeid关键字的实现问题,有人提到type_info的地址是存放在虚表的第一个位置上,颇觉得不妥,于是我在vc2003下实验了一番
    在vc下,使用typeid的时候,如果typeid施加给的类型是没有vptr的class或者根本不是class
那么汇编是
mov  dword ptr [addr],offset A `RTTI Type Descriptor' (42AD40h)
也就是编译器生成一个简单的type_info对象的表,并且在编译期静态决定下标,做一个简单查表操作。
如果typeid的操作对象是具有vptr的class,但是并不是一个引用或者指针的解引用形式,例如
 A a;
typeid(a);  
那么仍然仅仅会做查表操作
如果typeid的操作对象是具有vptr的class,并且是引用或者指针的解引用形式,例如
 A  * p  =   new  A;
A &  r  =   * p;
typeid( * p);
typeid(r);  
那么就会调用一个叫___RTtypeid的函数,并通过某种方法来获取type_info对象
下面是___RTtypeid的反汇编,这里只列出关键的几条指令
 0041213E  mov         ecx,dword ptr [inptr]    ;inptr是对象的地址
 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]   
基本上等价于C语言的
 int  a1  =  ( int )p;  // p是对象的地址 
 int  a2  =   * ( int * )a1  -   4 ;
 int  a3  =   * ( int * )a2  +   12 ;
 int  a4  =   * ( int * )a3;  
 
那么从这段代码可以看出vc下type_info对象的存放位置[如下图]
 
也就虚表下标为-1的位置上存放了一个指向一个未知的表的指针(暂且将此表命名为runtime_info_table)
runtime_info_table的第4格上存放了type_info对象的地址
至于runtime_info_table里前3格上存放的是什么, 还需要再研究研究
一般来说它们全是0, 但是对于多重虚继承的类, 第二格上会是4, 可能和指针的偏移量有关.
	posted on 2006-10-26 10:46 
shifan3 阅读(3376) 
评论(5)  编辑 收藏 引用  所属分类: 
C++