Howto:从C++对象指针得到类名
JAVA程序在运行的时候,有丰富的动态类型信息。而C++则困难的多。C++的运行时类型信息有3种实现方式:语言本身的RTTI、MFC的CObject、QT的moc。下面仅介绍前两种。
一、语言本身的RTTI:
如果是POD类型,如:
class PodPoint{
public:
int x;
int y;
};
那么它和C语言中的struct没有什么区别。sizeof(PodPoint)=8。
偏移值 内容
0 x
4 y
别妄想能从它的对象指针中得到什么类型信息。
如果它有虚函数,那么就不一样了
class PodPoint{
public:
int x;
int y;
virtual ~PodPoint(){};
};
在32位程序中,sizeof(PodPoint)=12。这是因为凡是有虚函数,就必须有vtable。所以PodPoint的实际布局就变成了这样:
偏移值 内容
0 指向vtable的指针
4 x
8 y
如果编译的时候打开了RTTI(在vc2005及以上版本默认会打开),那么就很有意思了。在vtable[-1]的位置,是一个特殊的指针,指向RTTI Complete Object Locator,它的第12个字节开始,是一个指针,指向type_info对象。于是我就写了下面这样的代码:
void printMyClassInfo(void *p){
type_info*** vtable=(type_info***)(*(int*)p);
type_info** v1=vtable[-1];
type_info* v=v1[3];
printf("%s\n",v->name());
}
在有vtable的情况下,这个函数工作的非常好。
二、MFC的RTTI
MFC中的大多数对象都从CObject继承而来,例如:
class MyPoint:public CObject{
public:
int x;
int y;
DECLARE_DYNAMIC(MyPoint)
};
IMPLEMENT_DYNAMIC(MyPoint,CObject)
那么我们就可以通过调用CObject的
virtual CRuntimeClass* GetRuntimeClass() const
来得到类名。这个函数一般就在vtable的第一个。
代码如下:
void printClassInfo(void *p){
int vtable=*(int*)p;
CRuntimeClass* info;
__asm{
mov ecx,p;
mov eax,vtable;
call [eax];
mov info,eax;
}
printf("%s",info->m_lpszClassName);
};
假如将上面的IMPLEMENT_DYNAMIC和DECLARE_DYNAMIC去掉,那么输出的结果将是”CObject”,而不是”MyPoint”,原因很简单。因为子类没有覆盖基类的这个方法嘛。
作者 snnn
补充:软件开发 , C++ ,