当前位置:编程学习 > C/C++ >>

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++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,