对象与对象的类型信息----获取对象的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
5
using
namespace std;
6
class Aclass
7
{
8
public:
9
int a;
10
virtual void setA(int tmp)
11
{
12
a=tmp;
13
cout<<a<<endl;
14
}
15
};
16
class Bclass:
public Aclass
17
{
18
public:
19
virtual void setA(int tmp)
20
{
21
a=tmp+10;
22
cout<<a<<endl;
23
}
24
public:
25
void print()
26
{
27
cout<<a<<endl;
28
}
29
};
30
class Cclass:
public Bclass
31
{
32
};
33
typedef unsigned
long DWORD;
34
struct TypeDescriptor
35
{
36
DWORD ptrToVTable;
37
DWORD spare;
38
char name[8];
39
};
40
struct PMD
41
{
42
43
int mdisp; //member displacement
44
45
int pdisp; //vbtable displacement
46
47
int vdisp; //displacement inside vbtable
48
49
};
50
struct 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
64
struct 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
77
struct 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
95
int _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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

输出结果:
在RTTI运行时结构体中包含许多丰富的信息,甚至我们可以利用一个实例的RTTI信息去复原整个类继承图谱
而对于dynamic_cast也是利用这个信息来准确的识别实例所对应的类型,不过如果对于没有多态的实例,dynamic_cast所做的也只是和编译器类型转换一样的事情,仅仅是通过类型和继承关系进行转换,还是看例子吧:
1
class mother
2
{
3
int a;
4
int b;
5
};
6
class father
7
{
8
double c;
9
};
10
class son:
public mother,
public father
11
{
12
char a;
13
short c;
14
};
15
16
int _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
}
运行会得到以下错误:

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

error C2683: “dynamic_cast”:“mother”不是多态类型
修改如下
class mother
{
int a;
int b;
virtual void fun()
{
}
};
一切正常
就说这么多吧,欢迎多交流