在 vs2010中的typeinfo.h 中 有一个叫 type_info的类 类的接口如下:
class type_info {
public:
virtual __thiscall ~type_info();
int __thiscall operator==(_In_ const type_info& _Rhs) const;
int __thiscall operator!=(_In_ const type_info& _Rhs) const;
int __thiscall before(_In_ const type_info& _Rhs) const;
private:
void *_M_data;
char _M_d_name[1];
__thiscall type_info(_In_ const type_info& _Rhs);
type_info& __thiscall operator=(_In_ const type_info& _Rhs);
};
这个类型 有两个变量 _M_data( 4 字节 ) M_d_name (可扩展字节)存储 类型的名字 因为这个类中的析构函数是虚函数
所以type_info 对象中必须保存一个虚函数表指针( 4 字节 ) 所以 这个类型的对象 总共有:4 + 4 + 类型名字的长度
type_info 对象 模型:
每种类型在内存中 都有其对应的 type_info对象 而且只有一份 。
比如:
class A{};
class B{};
class C{};
A类型 在内存中,有一个type_info 对象
B类型 在内存中,有一个type_info 对象
C类型 在内存中,有一个type_info 对象
A* 类型(指针类型) 在内存中,有一个type_info 对象
A** 类型(双指针类型) 在内存中,有一个type_info 对象
所以:
A a, a1; // (a , a1 是同种类型 )
A* pA, pA1; // (pA, pA1 是同种类型)
B b;
const type_info typeid(类型或类型对象)
typeid 是编译器,在编译期(不是程序运行期)根据传入的参数(类型或者类型对象【编译器可以根据类型对象的声明,知道对象的类型】)来返回对应类型的 type_info对象
class CType {};
void main()
{
CType type;
CType type1;
void* pCType = (void*)&typeid(CType); //获得类型CType的type_info的地址
printf("pCType = %x\n", pCType);
void* pType = (void*)&typeid(type); //获得类型CType的type_info的地址
printf("pType = %x\n", pType);
void* pType1 = (void*)&typeid(type1); //获得类型CType的type_info的地址
printf("pType1 = %x\n", pType1);
void* pCType_p = (void*)&typeid(CType*);//获得类型CType*的type_info的地址
printf("pCType_p = %x\n", pCType_p);
void* pCType_pp = (void*)&typeid(CType**);//获得类型CType**的type_info的地址
printf("pCType_pp = %x\n", pCType_pp);
while (true);
}
&type_info+9 == &_M_d_name[1]
const type_info typeid(类型或类型对象)
class type_info
{
public:
......
int operator==( const type_info& _Rhs) const;
......
}
其中 operator == 大致如下
int type_info:: operator == ( const type_info& _Rhs) const
{
return strcmp( &this._M_d_name[1], &_Rhs._M_d_name[1] );
}
我们来调试一下 typeid(CType) == typeid(type) 来推测一下 type_info::operator == 是否正确:
#include <stdio.h>
#include <typeinfo.h>
class CType{};
void main()
{
CType type;
if(typeid(CType) == typeid(type))
{
printf("test\n");
}
}
if(typeid(CType) == typeid(type))
008F13FE mov esi,esp
008F1400 push offset CType `RTTI Type Descriptor' (8F7000h) ;压入参数 typeid(type)
008F1405 mov ecx,offset CType `RTTI Type Descriptor' (8F7000h) ;ecx 为this指针 ecx为 typeid(CType)
008F140A call dword ptr [__imp_type_info::operator== (8F82C4h)] ; 调用 operator ==
看一下 __imp_type_info::operator == 的实现
0F31A3B0 mov edi,edi
0F31A3B2 push ebp
0F31A3B3 mov ebp,esp
0F31A3B5 push ecx
0F31A3B6 mov dword ptr [ebp-4],ecx // this 指针 &type_info 【CType】
0F31A3B9 mov eax,dword ptr [this]
0F31A3BC add eax,9 // &type_info + 9 【CType】 &_M_d_name[1]
0F31A3BF push eax // 入参
0F31A3C0 mov ecx,dword ptr [rhs]
0F31A3C3 add ecx,9 // &type_info + 9 【type】 &_M_d_name[1]
0F31A3C6 push ecx // 入参
0F31A3C7 call strcmp (0F29D430h) // 调用 strcmp比较字符串
0F31A3CC add esp,8
0F31A3CF neg eax
0F31A3D1 sbb eax,eax
0F31A3D3 add eax,1
0F31A3D6 mov esp,ebp
0F31A3D8 pop ebp
0F31A3D9 ret 4
可以看到最终就是调用 strcmp 比较 type_info的 &_M_d_name[1] 存储的字符串。如果相同,则是同一类型