RTTI (Run Time Type info)

这个神奇的东西用于存储类的相关信息,用于在运行时识别类对象的信息。C++ 里面只记录的类的名字和类的继承关系链。使得编译成二进制的代码,对象可以知道自己的名字(ASCII),以及在继承链中的位置。

C++ 里面提供 一个关键字 typeid , 一个数据类型 typeinfo,以及对应的头文件 typeinfo.h

1 #include <iostream>
2 #include <typeinfo>
3 using namespace std;
4
5 class Base
6 {
7 public:
8 virtual void f() {} // it must need the virtual table
9 };
10
11
12 class Derive: public Base
13 {
14
15 };
16
17
18 class Derive2: public Base
19 {
20
21 };
22
23 void f(Base* pbase)
24 {
25 const type_info& typeinfo = typeid(pbase);
26 cout << typeinfo.name()<<endl;
27
28
29 if(NULL != dynamic_cast<Derive*>(pbase))
30 {
31 cout<<"type: Derive"<<endl;
32 }
33 else if(NULL != dynamic_cast<Derive2*>(pbase))
34 {
35 cout<<"type: Derive2"<<endl;
36 }
37 else
38 {
39 //ASSERT(0)
40 }
41 }
42
43
44 int main()
45 {
46 Base *pbase1 = new Derive();
47 f(pbase1);
48
49 Base* pbase = new Derive2();
50 f(pbase);
51 }

out put:

1 class Base *
2 type: Derive
3 class Base *
4 type: Derive2

可见 Dynamic 是运行时确定的,是安全的。 那么

1. RTTI 的信息如何和对象绑定在一起?什么时候绑定的?

2. 为什么dynam_cast 必须要求转换的类型之间要有虚函数?否则编译通不过。

下面来回答这个问题。

3.RTTI 如何与对象绑定

google,找资料。 下面的图来自于 “Inside C++ Model”, RTTI 的info 是如何和对象之间的关系:

class Point
{
public:
Point( float xval );
virtual ~Point();
float x() const;
static int PointCount();
protected:
virtual ostream& print( ostream &os ) const;
float _x;
static int _point_count;
};

其内存中模型:

明显RTTI info 存在于虚表的第一项。第二个问题就可以回答,因为RTTI 依赖于虚表,所以用dynamic_cast 对应的类一定要有虚函数。

下面在VC中验证一下,

在VC中,我们知道虚指针指向虚表,对应的虚表第一项就是第一个虚函数。如果我们认为虚函数构成虚表,那么就可以认为RTTI info 就走虚表的紧邻上面。

下面验证:

1. 在VC 中查看RTTI中类名字

从上面图表可见,RTTI 对应的内容是空的。那么VC的实现和 书中的模型不一致吗?难道RTTI不在虚表的上面吗 ?接着有了下面的验证:

2. 把虚表上面指向RTTI info 的地址,给设置为0, 那么typeid 还可以工作吗? Dynamic_cast 还可以工作吗?如果还可以工作,则说明这个地址指向的数据无关。

如果将虚表上的RTTI的指针置空,dynamic_cast 就不能运行,抛出异常“std:: __non_rtti_object” . 那说明这个地址,还是与RTTI有关。那问题出在哪里?

尝试在google 里面搜索,但是未果。 那么Dynamic_cast 的依赖于 RTTI的信息,那么Dynamic_cast的实现着手看看. 查看一下 他的汇编代码。 于是有了下面的实验。

3. RTTI 在VC里面如何实现的。

将上面的代码以汇编形式输出,查看。

24 : Derive * pderive = dynamic_cast<Derive*>(pbase);
push 0
push OFFSET ??_R0?AVDerive@@@8
push OFFSET ??_R0?AVBase@@@8
push 0
mov eax, DWORD PTR _pbase$[ebp]
push eax
call ___RTDynamicCast
add esp, 20 ; 00000014H
mov DWORD PTR _pderive$[ebp], eax

发现 dynamic_cast的实现依赖于 对象本身,以及 ??_R0?AVDerive@@@8 和 ??_R0?AVBase@@@8 .  于是继续查看代码

1 ; Listing generated by Microsoft (R) Optimizing Compiler Version 14.00.50727.762
2
3 TITLE c:\Documents and Settings\zhangroc\Desktop\TW\Test\static_cast\static_cast.cpp
4 .686P
5 .XMM
6 include listing.inc
7 .model flat
8
9 INCLUDELIB MSVCRTD
10 INCLUDELIB OLDNAMES
11
12 PUBLIC ??_C@_0P@GHFPNOJB@bad?5allocation?$AA@ ; `string'
13 _DATA SEGMENT
14 __bad_alloc_Message DD FLAT:??_C@_0P@GHFPNOJB@bad?5allocation?$AA@
15 _DATA ENDS
16 ; COMDAT ??_C@_0P@GHFPNOJB@bad?5allocation?$AA@
17 CONST SEGMENT
18 ??_C@_0P@GHFPNOJB@bad?5allocation?$AA@ DB 'bad allocation', 00H ; `string'
19 CONST ENDS
20 PUBLIC ??_R0?AVBase@@@8 ; Base `RTTI Type Descriptor'
21 PUBLIC ??_R0?AVDerive@@@8 ; Derive `RTTI Type Descriptor'
22 PUBLIC ??0Derive@@QAE@XZ ; Derive::Derive
23 PUBLIC _main
24 EXTRN ___RTDynamicCast:PROC
25 EXTRN ??2@YAPAXI@Z:PROC ; operator new
26 EXTRN __RTC_CheckEsp:PROC
27 EXTRN __RTC_Shutdown:PROC
28 EXTRN __RTC_InitBase:PROC
29 EXTRN ??_7type_info@@6B@:QWORD ; type_info::`vftable'
30 ; COMDAT ??_R0?AVBase@@@8
31 ; File c:\documents and settings\zhangroc\desktop\tw\test\static_cast\static_cast.cpp
32 _DATA SEGMENT
33 ??_R0?AVBase@@@8 DD FLAT:??_7type_info@@6B@ ; Base `RTTI Type Descriptor'
34 DD 00H
35 DB '.?AVBase@@', 00H
36 _DATA ENDS
37 ; COMDAT ??_R0?AVDerive@@@8
38 _DATA SEGMENT
39 ??_R0?AVDerive@@@8 DD FLAT:??_7type_info@@6B@ ; Derive `RTTI Type Descriptor'
40 DD 00H
41 DB '.?AVDerive@@', 00H
42 _DATA ENDS
43 ; COMDAT rtc$TMZ
44 rtc$TMZ SEGMENT
45 __RTC_Shutdown.rtc$TMZ DD FLAT:__RTC_Shutdown
46 rtc$TMZ ENDS
47 ; COMDAT rtc$IMZ
48 rtc$IMZ SEGMENT
49 __RTC_InitBase.rtc$IMZ DD FLAT:__RTC_InitBase
50 ; Function compile flags: /Odtp /RTCsu /ZI
51 rtc$IMZ ENDS
52 ; COMDAT _main
53 _TEXT SEGMENT
54 tv69 = -256 ; size = 4
55 $T3121 = -248 ; size = 4
56 _pderive$ = -44 ; size = 4
57 _rtti$ = -32 ; size = 4
58 _ptable$ = -20 ; size = 4
59 _pbase$ = -8 ; size = 4
60 _main PROC ; COMDAT
61
62 ; 19 : {
63
64 push ebp
65 mov ebp, esp
66 sub esp, 256 ; 00000100H
67 push ebx
68 push esi
69 push edi
70 lea edi, DWORD PTR [ebp-256]
71 mov ecx, 64 ; 00000040H
72 mov eax, -858993460 ; ccccccccH
73 rep stosd
74
75 ; 20 : Base *pbase = new Derive();
76
77 push 4
78 call ??2@YAPAXI@Z ; operator new
79 add esp, 4
80 mov DWORD PTR $T3121[ebp], eax
81 cmp DWORD PTR $T3121[ebp], 0
82 je SHORT $LN3@main
83 mov ecx, DWORD PTR $T3121[ebp]
84 call ??0Derive@@QAE@XZ
85 mov DWORD PTR tv69[ebp], eax
86 jmp SHORT $LN4@main
87 $LN3@main:
88 mov DWORD PTR tv69[ebp], 0
89 $LN4@main:
90 mov eax, DWORD PTR tv69[ebp]
91 mov DWORD PTR _pbase$[ebp], eax
92
93 ; 21 : int *ptable = (int*)(*(int*)pbase);
94
95 mov eax, DWORD PTR _pbase$[ebp]
96 mov ecx, DWORD PTR [eax]
97 mov DWORD PTR _ptable$[ebp], ecx
98
99 ; 22 : int *rtti = ptable -1;
100
101 mov eax, DWORD PTR _ptable$[ebp]
102 sub eax, 4
103 mov DWORD PTR _rtti$[ebp], eax
104
105 ; 23 :
106 ; 24 : Derive * pderive = dynamic_cast<Derive*>(pbase);
107
108 push 0
109 push OFFSET ??_R0?AVDerive@@@8
110 push OFFSET ??_R0?AVBase@@@8
111 push 0
112 mov eax, DWORD PTR _pbase$[ebp]
113 push eax
114 call ___RTDynamicCast
115 add esp, 20 ; 00000014H
116 mov DWORD PTR _pderive$[ebp], eax
117
118 ; 25 :
119 ; 26 : }
120
121 xor eax, eax
122 pop edi
123 pop esi
124 pop ebx
125 add esp, 256 ; 00000100H
126 cmp ebp, esp
127 call __RTC_CheckEsp
128 mov esp, ebp
129 pop ebp
130 ret 0
131 _main ENDP
132 _TEXT ENDS
133 PUBLIC ??_7Derive@@6B@ ; Derive::`vftable'
134 PUBLIC ??0Base@@QAE@XZ ; Base::Base
135 PUBLIC ??_R4Derive@@6B@ ; Derive::`RTTI Complete Object Locator'
136 PUBLIC ??_R3Derive@@8 ; Derive::`RTTI Class Hierarchy Descriptor'
137 PUBLIC ??_R2Derive@@8 ; Derive::`RTTI Base Class Array'
138 PUBLIC ??_R1A@?0A@EA@Derive@@8 ; Derive::`RTTI Base Class Descriptor at (0,-1,0,64)'
139 PUBLIC ??_R1A@?0A@EA@Base@@8 ; Base::`RTTI Base Class Descriptor at (0,-1,0,64)'
140 PUBLIC ??_R3Base@@8 ; Base::`RTTI Class Hierarchy Descriptor'
141 PUBLIC ??_R2Base@@8 ; Base::`RTTI Base Class Array'
142 PUBLIC ?f@Base@@UAEXXZ ; Base::f
143 ; COMDAT ??_R2Base@@8
144 rdata$r SEGMENT
145 ??_R2Base@@8 DD FLAT:??_R1A@?0A@EA@Base@@8 ; Base::`RTTI Base Class Array'
146 rdata$r ENDS
147 ; COMDAT ??_R3Base@@8
148 rdata$r SEGMENT
149 ??_R3Base@@8 DD 00H ; Base::`RTTI Class Hierarchy Descriptor'
150 DD 00H
151 DD 01H
152 DD FLAT:??_R2Base@@8
153 rdata$r ENDS
154 ; COMDAT ??_R1A@?0A@EA@Base@@8
155 rdata$r SEGMENT
156 ??_R1A@?0A@EA@Base@@8 DD FLAT:??_R0?AVBase@@@8 ; Base::`RTTI Base Class Descriptor at (0,-1,0,64)'
157 DD 00H
158 DD 00H
159 DD 0ffffffffH
160 DD 00H
161 DD 040H
162 DD FLAT:??_R3Base@@8
163 rdata$r ENDS
164 ; COMDAT ??_R1A@?0A@EA@Derive@@8
165 rdata$r SEGMENT
166 ??_R1A@?0A@EA@Derive@@8 DD FLAT:??_R0?AVDerive@@@8 ; Derive::`RTTI Base Class Descriptor at (0,-1,0,64)'
167 DD 01H
168 DD 00H
169 DD 0ffffffffH
170 DD 00H
171 DD 040H
172 DD FLAT:??_R3Derive@@8
173 rdata$r ENDS
174 ; COMDAT ??_R2Derive@@8
175 rdata$r SEGMENT
176 ??_R2Derive@@8 DD FLAT:??_R1A@?0A@EA@Derive@@8 ; Derive::`RTTI Base Class Array'
177 DD FLAT:??_R1A@?0A@EA@Base@@8
178 rdata$r ENDS
179 ; COMDAT ??_R3Derive@@8
180 rdata$r SEGMENT
181 ??_R3Derive@@8 DD 00H ; Derive::`RTTI Class Hierarchy Descriptor'
182 DD 00H
183 DD 02H
184 DD FLAT:??_R2Derive@@8
185 rdata$r ENDS
186 ; COMDAT ??_R4Derive@@6B@
187 rdata$r SEGMENT
188 ??_R4Derive@@6B@ DD 00H ; Derive::`RTTI Complete Object Locator'
189 DD 00H
190 DD 00H
191 DD FLAT:??_R0?AVDerive@@@8
192 DD FLAT:??_R3Derive@@8
193 rdata$r ENDS
194 ; COMDAT ??_7Derive@@6B@
195 CONST SEGMENT
196 ??_7Derive@@6B@ DD FLAT:??_R4Derive@@6B@ ; Derive::`vftable'
197 DD FLAT:?f@Base@@UAEXXZ
198 ; Function compile flags: /Odtp /RTCsu /ZI
199 CONST ENDS
200 ; COMDAT ??0Derive@@QAE@XZ
201 _TEXT SEGMENT
202 _this$ = -8 ; size = 4
203 ??0Derive@@QAE@XZ PROC ; Derive::Derive, COMDAT
204 ; _this$ = ecx
205 push ebp
206 mov ebp, esp
207 sub esp, 204 ; 000000ccH
208 push ebx
209 push esi
210 push edi
211 push ecx
212 lea edi, DWORD PTR [ebp-204]
213 mov ecx, 51 ; 00000033H
214 mov eax, -858993460 ; ccccccccH
215 rep stosd
216 pop ecx
217 mov DWORD PTR _this$[ebp], ecx
218 mov ecx, DWORD PTR _this$[ebp]
219 call ??0Base@@QAE@XZ
220 mov eax, DWORD PTR _this$[ebp]
221 mov DWORD PTR [eax], OFFSET ??_7Derive@@6B@
222 mov eax, DWORD PTR _this$[ebp]
223 pop edi
224 pop esi
225 pop ebx
226 add esp, 204 ; 000000ccH
227 cmp ebp, esp
228 call __RTC_CheckEsp
229 mov esp, ebp
230 pop ebp
231 ret 0
232 ??0Derive@@QAE@XZ ENDP ; Derive::Derive
233 ; Function compile flags: /Odtp /RTCsu /ZI
234 _TEXT ENDS
235 ; COMDAT ?f@Base@@UAEXXZ
236 _TEXT SEGMENT
237 _this$ = -8 ; size = 4
238 ?f@Base@@UAEXXZ PROC ; Base::f, COMDAT
239 ; _this$ = ecx
240
241 ; 8 : virtual void f() {}
242
243 push ebp
244 mov ebp, esp
245 sub esp, 204 ; 000000ccH
246 push ebx
247 push esi
248 push edi
249 push ecx
250 lea edi, DWORD PTR [ebp-204]
251 mov ecx, 51 ; 00000033H
252 mov eax, -858993460 ; ccccccccH
253 rep stosd
254 pop ecx
255 mov DWORD PTR _this$[ebp], ecx
256 pop edi
257 pop esi
258 pop ebx
259 mov esp, ebp
260 pop ebp
261 ret 0
262 ?f@Base@@UAEXXZ ENDP ; Base::f
263 _TEXT ENDS
264 PUBLIC ??_7Base@@6B@ ; Base::`vftable'
265 PUBLIC ??_R4Base@@6B@ ; Base::`RTTI Complete Object Locator'
266 ; COMDAT ??_R4Base@@6B@
267 rdata$r SEGMENT
268 ??_R4Base@@6B@ DD 00H ; Base::`RTTI Complete Object Locator'
269 DD 00H
270 DD 00H
271 DD FLAT:??_R0?AVBase@@@8
272 DD FLAT:??_R3Base@@8
273 rdata$r ENDS
274 ; COMDAT ??_7Base@@6B@
275 CONST SEGMENT
276 ??_7Base@@6B@ DD FLAT:??_R4Base@@6B@ ; Base::`vftable'
277 DD FLAT:?f@Base@@UAEXXZ
278 ; Function compile flags: /Odtp /RTCsu /ZI
279 CONST ENDS
280 ; COMDAT ??0Base@@QAE@XZ
281 _TEXT SEGMENT
282 _this$ = -8 ; size = 4
283 ??0Base@@QAE@XZ PROC ; Base::Base, COMDAT
284 ; _this$ = ecx
285 push ebp
286 mov ebp, esp
287 sub esp, 204 ; 000000ccH
288 push ebx
289 push esi
290 push edi
291 push ecx
292 lea edi, DWORD PTR [ebp-204]
293 mov ecx, 51 ; 00000033H
294 mov eax, -858993460 ; ccccccccH
295 rep stosd
296 pop ecx
297 mov DWORD PTR _this$[ebp], ecx
298 mov eax, DWORD PTR _this$[ebp]
299 mov DWORD PTR [eax], OFFSET ??_7Base@@6B@
300 mov eax, DWORD PTR _this$[ebp]
301 pop edi
302 pop esi
303 pop ebx
304 mov esp, ebp
305 pop ebp
306 ret 0
307 ??0Base@@QAE@XZ ENDP ; Base::Base
308 _TEXT ENDS
309 END

原来虚表上面指向是一个 Derive::`RTTI Complete Object Locator 。 用google 搜索下面的该关键字,有了下面的文章
http://www.openrce.org/articles/full_view/23
和该图:

谜底揭晓: 原来虚表上面的地址是指向一个结构 Derive::`RTTI Complete Object Locator , 这个结构指向该类的名字,和其对象继承链。

这就回答了第一个问题,RTTI info 如何和对象绑定的? 在对象创建的时候,调用构造函时候,创建虚表以及RTTI info,这样dynamic cast 就可以去访问RTTI,从而保证安全。

同样有个一问题,那就是RTTI 效率底下,试下如果一个类其继承多层,而且有多继承,那么查找链就相当遍历一个链表。

转自:http://www.cnblogs.com/zhyg6516/archive/2011/03/07/1971898.html

RTTI的实现(vc)--转载的更多相关文章

  1. vs2010中文简体版下载链接(含中文msdn)

    昨天朋友说vs2010中文版能够下载了,自己開始还不相信,正好周末,于是就下载了试一下 安装了果然是中文版,本来是msdn订阅用户才干够下载的,感谢上传的网友. 文件名称 cn_visual_stud ...

  2. vs2010下载链接中国简体(中国含msdn)

    昨天一个朋友说vs2010中国版可下载,我开始不相信.只是周末.所以,我下载一试 果然,安装了中国版,原本msdn订户才能够下载,感谢朋友们上传. 文件名 cn_visual_studio_2010_ ...

  3. 【转载】VC维的来龙去脉

    本文转载自 火光摇曳 原文链接:VC维的来龙去脉 目录: 说说历史 Hoeffding不等式 Connection to Learning 学习可行的两个核心条件 Effective Number o ...

  4. 转载 VC 2010下安装OpenCV2.4.4

    说明: 1.安装平台:32位XP,VS2010: 2.OpenCV 2.4.4不支持VC 6.0: 3.网上有很多用CMake编译OpenCV的安装教程,这里建议先不要自己编译,如果使用预编译好的库有 ...

  5. VC++6.0 下配置 pthread库2010年12月12日 星期日 13:14VC下的pthread多线程编程 转载

    VC++6.0 下配置 pthread库2010年12月12日 星期日 13:14VC下的pthread多线程编程     转载 #include <stdio.h>#include &l ...

  6. [转载]解决win10 VC++6.0 应用程序无法正常运行 0xc0000142

    本文转载自http://blog.csdn.net/w_9449/article/details/52864135 转载请申明哦,其实我发现自从我在贴吧发了帖子后,就冒出了不少帖子.经验.当然方法和我 ...

  7. VC维的来龙去脉——转载

    VC维的来龙去脉——转载自“火光摇曳” 在研究VC维的过程中,发现一篇写的很不错的VC维的来龙去脉的文章,以此转载进行学习. 原文链接,有兴趣的可以参考原文进行研究学习 目录: 说说历史 Hoeffd ...

  8. 【转载】VC维,结构风险最小化

    以下文章转载自http://blog.sina.com.cn/s/blog_7103b28a0102w9tr.html 如有侵权,请留言,立即删除. 1 VC维的描述和理解 给定一个集合S={x1,x ...

  9. 转载:HTuple数据和VC数据的相互赋值

    转载来自:http://blog.csdn.net/taily_duan/article/details/51026260 HTuple和VC数据的相互赋值 // HTuple→VC 数据类型转换 H ...

随机推荐

  1. C#字段中加入list<类字段> 的两种写法

    类1 public class NumCon { public string zsNum { get; set; } } 类2 public class RepeatMess //重复数据响应 { p ...

  2. 20145225《Java程序设计》 2015—2016年学期课程总结

    20145225<Java程序设计> 2015—2016年学期课程总结 读书笔记链接汇总 1.2016年2月25日 <Java程序设计>课程准备之问卷调查 摘要: 一.你对自己 ...

  3. Servlet 的认识

    Servlet的响应过程:1,web 客户端向 Servlet容器发出http请求2,Servlet容器接收 客户端发来的请求3,创建一个 HttpRequest对象,将客户端发来的请求信息封装到这个 ...

  4. 分布式日志2 用redis的队列写日志

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...

  5. 0909 45作业one

    1.编译原理学什么? 答: 初遇编译原理,我知道编译原理是计算机专业设置的一门重要的专业课程,主要是介绍编译程序构造的一般原理和基本方法.其内容大概包括语言和文法.词法分析.语法分析.语法制导翻译.中 ...

  6. myfocus焦点库的引用

    1.在Html中引入相关的文件:引入风格文件(js/css/jq) 2.创建myFocus标准的Html的结构并填充内容 <div id="picBox"> <d ...

  7. hdoj 2680 choose the best route

    Problem Description One day , Kiki wants to visit one of her friends. As she is liable to carsicknes ...

  8. JS实现隔行变色,鼠标移入高亮

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 31.0px Consolas; color: #2b7ec3 } p.p2 { margin: 0.0px ...

  9. Please set registry key HKLM\Microsoft\.NET Framework\InstallRoot to point to the .NET Framework

    安装.NET程序时会提示“Please set registry key HKLM\Microsoft\.NET Framework\InstallRoot to point to the .NET ...

  10. 1.一起来学hibernate之hibernate简介

    一.简介 Hibernate,是一个开源的ORM框架.所谓的ORM,即object relative mapping,就是对象关系映射. 那什么是对象关系映射? 对象,即java类,又称为实体类,对象 ...