RTTI的实现(vc)--转载
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)--转载的更多相关文章
- vs2010中文简体版下载链接(含中文msdn)
昨天朋友说vs2010中文版能够下载了,自己開始还不相信,正好周末,于是就下载了试一下 安装了果然是中文版,本来是msdn订阅用户才干够下载的,感谢上传的网友. 文件名称 cn_visual_stud ...
- vs2010下载链接中国简体(中国含msdn)
昨天一个朋友说vs2010中国版可下载,我开始不相信.只是周末.所以,我下载一试 果然,安装了中国版,原本msdn订户才能够下载,感谢朋友们上传. 文件名 cn_visual_studio_2010_ ...
- 【转载】VC维的来龙去脉
本文转载自 火光摇曳 原文链接:VC维的来龙去脉 目录: 说说历史 Hoeffding不等式 Connection to Learning 学习可行的两个核心条件 Effective Number o ...
- 转载 VC 2010下安装OpenCV2.4.4
说明: 1.安装平台:32位XP,VS2010: 2.OpenCV 2.4.4不支持VC 6.0: 3.网上有很多用CMake编译OpenCV的安装教程,这里建议先不要自己编译,如果使用预编译好的库有 ...
- 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 ...
- [转载]解决win10 VC++6.0 应用程序无法正常运行 0xc0000142
本文转载自http://blog.csdn.net/w_9449/article/details/52864135 转载请申明哦,其实我发现自从我在贴吧发了帖子后,就冒出了不少帖子.经验.当然方法和我 ...
- VC维的来龙去脉——转载
VC维的来龙去脉——转载自“火光摇曳” 在研究VC维的过程中,发现一篇写的很不错的VC维的来龙去脉的文章,以此转载进行学习. 原文链接,有兴趣的可以参考原文进行研究学习 目录: 说说历史 Hoeffd ...
- 【转载】VC维,结构风险最小化
以下文章转载自http://blog.sina.com.cn/s/blog_7103b28a0102w9tr.html 如有侵权,请留言,立即删除. 1 VC维的描述和理解 给定一个集合S={x1,x ...
- 转载:HTuple数据和VC数据的相互赋值
转载来自:http://blog.csdn.net/taily_duan/article/details/51026260 HTuple和VC数据的相互赋值 // HTuple→VC 数据类型转换 H ...
随机推荐
- C#字段中加入list<类字段> 的两种写法
类1 public class NumCon { public string zsNum { get; set; } } 类2 public class RepeatMess //重复数据响应 { p ...
- 20145225《Java程序设计》 2015—2016年学期课程总结
20145225<Java程序设计> 2015—2016年学期课程总结 读书笔记链接汇总 1.2016年2月25日 <Java程序设计>课程准备之问卷调查 摘要: 一.你对自己 ...
- Servlet 的认识
Servlet的响应过程:1,web 客户端向 Servlet容器发出http请求2,Servlet容器接收 客户端发来的请求3,创建一个 HttpRequest对象,将客户端发来的请求信息封装到这个 ...
- 分布式日志2 用redis的队列写日志
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...
- 0909 45作业one
1.编译原理学什么? 答: 初遇编译原理,我知道编译原理是计算机专业设置的一门重要的专业课程,主要是介绍编译程序构造的一般原理和基本方法.其内容大概包括语言和文法.词法分析.语法分析.语法制导翻译.中 ...
- myfocus焦点库的引用
1.在Html中引入相关的文件:引入风格文件(js/css/jq) 2.创建myFocus标准的Html的结构并填充内容 <div id="picBox"> <d ...
- hdoj 2680 choose the best route
Problem Description One day , Kiki wants to visit one of her friends. As she is liable to carsicknes ...
- JS实现隔行变色,鼠标移入高亮
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 31.0px Consolas; color: #2b7ec3 } p.p2 { margin: 0.0px ...
- 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 ...
- 1.一起来学hibernate之hibernate简介
一.简介 Hibernate,是一个开源的ORM框架.所谓的ORM,即object relative mapping,就是对象关系映射. 那什么是对象关系映射? 对象,即java类,又称为实体类,对象 ...