统计

  • 随笔 - 50
  • 文章 - 42
  • 评论 - 147
  • 引用 - 0

留言簿(6)

随笔分类

文章分类

Link

搜索

  •  

积分与排名

  • 积分 - 162594
  • 排名 - 161

最新评论

阅读排行榜

评论排行榜

对象与对象的类型信息----获取对象的RTTI信息

梦在天涯 在上篇文章里问可不可以研究下对象与对象的类型信息怎么联系起来的,就是当调用dynamic_cast的时候为什么能够正确的识别对象的类型

RTTI(Run Time Type Identification)运行时类型识别是有编译器在编译器生成的特殊类型信息,包括对象继承关系,对象本身的描述,RTTI是为多态而生成的信息,所以只有具有虚函数的对象在会生成

那RTTI在哪里呢?
MSVC编译器在vftable前设置了一个指针,指向叫做“Complete Object Locator”(完整对象定位器)的结构。这样称呼是因为它允许编译器从特定的vftable指针(因为一个类可能有若干vftable)找到完整对象的位置。COL就像如下定义:

请看如下代码:

  1#include "iostream"
  2#include "string"
  3
  4
  5using namespace std;
  6class Aclass
  7{
  8public:
  9     int a;
 10    virtual void setA(int tmp)
 11    {
 12        a=tmp;
 13        cout<<a<<endl;
 14    }

 15}
;
 16class Bclass:public Aclass
 17{
 18public:
 19    virtual void setA(int tmp)
 20    {
 21        a=tmp+10;
 22        cout<<a<<endl;
 23    }

 24public:
 25    void print()
 26    {
 27        cout<<a<<endl;
 28    }

 29}
;
 30class Cclass:public Bclass
 31{
 32}
;
 33typedef unsigned long DWORD;
 34struct TypeDescriptor
 35{
 36    DWORD ptrToVTable;
 37    DWORD spare;
 38    char name[8];
 39}
;
 40struct PMD
 41{
 42
 43    int mdisp;  //member displacement
 44
 45    int pdisp;  //vbtable displacement
 46
 47    int vdisp;  //displacement inside vbtable
 48
 49}
;
 50struct RTTIBaseClassDescriptor
 51
 52{
 53
 54    struct TypeDescriptor* pTypeDescriptor; //type descriptor of the class
 55
 56    DWORD numContainedBases; //number of nested classes following in the Base Class Array
 57
 58    struct PMD where;        //pointer-to-member displacement info
 59
 60    DWORD attributes;        //flags, usually 0
 61
 62}
;
 63
 64struct RTTIClassHierarchyDescriptor
 65{
 66
 67    DWORD signature;      //always zero?
 68
 69    DWORD attributes;     //bit 0 set = multiple inheritance, bit 1 set = virtual inheritance
 70
 71    DWORD numBaseClasses; //number of classes in pBaseClassArray
 72
 73    struct RTTIBaseClassArray* pBaseClassArray;
 74
 75}
;
 76
 77struct RTTICompleteObjectLocator
 78
 79{
 80
 81    DWORD signature; //always zero ?
 82
 83    DWORD offset;    //offset of this vtable in the complete class
 84
 85    DWORD cdOffset;  //constructor displacement offset
 86
 87    struct TypeDescriptor* pTypeDescriptor; //TypeDescriptor of the complete class
 88
 89    struct RTTIClassHierarchyDescriptor* pClassDescriptor; //describes inheritance hierarchy
 90
 91
 92}
;
 93
 94
 95int _tmain(int argc, _TCHAR* argv[])
 96{
 97    Aclass* ptra=new Bclass;
 98    int ** ptrvf=(int**)(ptra);
 99    RTTICompleteObjectLocator str=
100        *((RTTICompleteObjectLocator*)(*((int*)ptrvf[0]-1)));
101    //abstract class name from RTTI
102    string classname(str.pTypeDescriptor->name);
103    classname=classname.substr(4,classname.find("@@")-4);
104    cout<<classname<<endl;
105    system("pause");
106    return 0;
107}

108

输出结果:


在RTTI运行时结构体中包含许多丰富的信息,甚至我们可以利用一个实例的RTTI信息去复原整个类继承图谱

而对于dynamic_cast也是利用这个信息来准确的识别实例所对应的类型,不过如果对于没有多态的实例,dynamic_cast所做的也只是和编译器类型转换一样的事情,仅仅是通过类型和继承关系进行转换,还是看例子吧:

 1class mother
 2{
 3    int a;
 4    int b;
 5}
;
 6class father
 7{
 8    double c;
 9}
;
10class son:public mother,public father
11{
12    char a;
13    short c;
14}
;
15
16int _tmain(int argc, _TCHAR* argv[])
17{
18    mother* m=new son();
19    father* f=dynamic_cast<father*>(m);
20    system("pause");
21    return 0;
22}
运行会得到以下错误:
error C2683: “dynamic_cast”:“mother”不是多态类型
修改如下
class mother
{
 int a;
 int b;
 virtual void fun()
 {
 }
};
一切正常

就说这么多吧,欢迎多交流

posted on 2009-03-12 17:55 pear_li 阅读(4139) 评论(3)  编辑 收藏 引用 所属分类: C++

评论

# re: 对象与对象的类型信息----获取对象的RTTI信息 2009-03-12 21:32 梦在天涯

超好啊,原来真的在前面啊,看到C++对象模型说的,但是我确实是没有想到原来是在VTable - 1啊!
  回复  更多评论    

# re: 对象与对象的类型信息----获取对象的RTTI信息 2009-03-13 00:19 pear_li

@梦在天涯
呵呵,是啊,梦在天涯的确是看了好多书啊
  回复  更多评论    

# re: 对象与对象的类型信息----获取对象的RTTI信息 2010-08-22 00:19 tomren

不错,刚看到:)
  回复  更多评论    

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理