ImageVerifierCode 换一换
格式:DOCX , 页数:31 ,大小:22.98KB ,
资源ID:30049609      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/30049609.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(深入浅出MFC学习笔记第三章MFC六大关键技术之仿真类型识别动态创建.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

深入浅出MFC学习笔记第三章MFC六大关键技术之仿真类型识别动态创建.docx

1、深入浅出MFC学习笔记第三章MFC六大关键技术之仿真类型识别动态创建第三章:MFC六大关键技术之仿真:类型识别 深入理解MFC的内部运行原理,是本次学习深入浅出MFC的主要目的。要模仿的六大技术包括:1:MFC程序的初始化过程。2:RTTI(Runtime type identification)运行时类型识别。3:Dynamic creation 动态创建4:Persistence永久保存5:消息映射6:消息传递。RTTI(运行时类型识别) IsKindOf能够侦测某个对象是否属于某种类。即判断某一对象所属的类是否是父类或当前类; 要达到动态类型识别的能力,必须在构建类继承体系时记录必要的信

2、息,这被称为类型型录表。MFC以链表的方式建立了此表。 类型型录表的每个元素为CRuntimeClass类型,其定义为:cpp view plaincopy1 class CRuntimeClass 2 3 4 5 public: 6 7 LPCSTR m_lpszClassName;/对象所属类名 8 9 Int m_nObjectSize;/对象大小 10 11 UINT m_wSchema;/模式号 12 13 CObject *(PASCAL*m_pfnCreateObject)();/构建函数抽象类为NULL 14 15 CRuntimeClass *pBaseClasss;/基类C

3、RuntimeClass对象指针。 16 17 Static CRuntimeClass *pFirstClass;/链表头指针。 18 19 CRuntimeClass *m_pNextClass;/下一指针。 20 21 ; MFC使用此类作为每个类的成员变量。使用宏定义为每个类定义了自己的CRuntimeClass成员变量。DECLAR_DYNAMIC和IMPLENMENT_DYNAMIC宏使用这两个宏将CRuntimeClass对象不知不觉放到类之中。DECLARE_DYNMIC宏定义如下:cpp view plaincopy22 #define DELCARE_DYNMIC ( cl

4、ass_name ) 23 24 public: 25 26 static CRuntimeClass class#class_name 27 28 virtual CRuntimeClass *GetRuntimeClass()const; #用来告诉编译器把两个字符串连接起来。如果使用这个宏:DELCARE_DYNMIC(CView);那么预编译器将生成下列代码:cpp view plaincopy29 public: 30 31 static CRuntimeClass classCView; 32 33 virtual CRuntimeClass*GetRuntimeClass()co

5、nst; 以上代码仅仅是在类中定义CRuntimeClass对象,并定义一个返回CRuntimeClass对象地址的函数。注意CRuntimeClass是static的,也就是说同一种类继承体系的对象共享一个CRuntimeClass对象。初始化对象的内容以及建立类型型录表需要使用IMPLEMENT_DYNMIC宏。cpp view plaincopy34 #define IMPLEMENT_DYNMIC (class_name,base_class_name) 35 36 _IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,0xFFFF,NU

6、LL); 37 38 _IMPLEMENT_RUNTIMECLASS又是一个宏,它定义如下: 39 40 #define _IMPLEMENT_RUNTIMECLASS(class_name, 41 42 base_class_name,wSchema,pfnNew) 43 44 static char _lpsz#class_name=#class_name; 45 46 CRuntimeClass class_name:class#class_name= 47 48 _lpsz#class_name,sizeof(class_name), 49 50 wSchema,pfnNew, 51

7、52 RUNTIME_CLASS(base_class_name),NULL 53 54 ; 55 56 static AFX_CLASSINIT _init#class_name 57 58 ( & class_name:class#class_name); 59 60 CRuntimeClass *class_name:GetRuntimeClass()const 61 62 63 64 return &class_name:class#classname; 65 66 67 68 #define RUNTIME_CLASS(class_name) 69 70 ( &class_name:

8、class#class_name); AFX_CLASSINIT是一个类,看着跟宏定义似的,这样做很容易让人迷惑。它用于将本节点连接到类型型录表,定义如下:cpp view plaincopy71 class AFX_CLASSINIT 72 73 74 75 public: 76 77 AFX_CLASSINIT(CRuntimeClass*pNewClass)/构造函数 78 79 80 81 pNewClass-m_pNextClass=CRuntime:pFirstClass; 82 83 CRuntimeClass:pFirstClass =pNewClass; 84 85 86 8

9、7 ; 用法:cpp view plaincopy88 class CWnd:public CCmdTarget 89 90 91 92 public: 93 94 DECLARE_DYNAMIC(CWnd); 95 96 97 ; IMPLEMENT_DYNMIC(CWnd,CCmdTarget);代码展开后为;cpp view plaincopy98 class CWnd:public CCmdTarget 99 100 101 102 public: 103 104 static CRuntimeClass classCView; 105 106 virtual CRuntimeClas

10、s*GetRuntimeClass()const 107 108 109 110 ; 111 112 113 114 static char _lpszCWnd=CWnd; 115 116 CRuntimeClass CWnd:classCWnd= 117 118 119 120 _lpszCView , sizeof(CWnd) , FFFF,NULL , &Wnd:classCWnd , NULL); 121 122 ; 123 124 static AFX_CLASSINIT _init_CWnd(&CWnd:classCWnd); 125 126 127 128 Return &CWn

11、d:classCWnd; 129 130 定义宏的过程很复杂,但是一旦定义好之后,在使用时仅仅两句话就可以完成定义CRuntimeClass对象并且连接类型型录链表的工作。CObject是所有类的基类,也是链表的头,此类应特别定义,不能在CObject内使用定义好的宏。cpp view plaincopy131 class CObject 132 133 134 135 public: 136 137 virtual CRuntimeClass*GetRuntimeClass()const; 138 139 static CRuntimeClass classCObject; 140 141

12、; 142 143 static char szCobject=CObject; 144 145 struct CRuntimeClass CObject:classCObject= 146 147 148 149 szCObject ,sizeof(CObject),0xFFFF,NULL,NULL,NULL 150 151 ; 152 153 static AFX_CLASSINIT _init_CObject(&Cobject:classObject); 154 155 CRuntimeClass *CObject:GetRuntimeClass()const 156 157 158 1

13、59 return &CObject:classCObject; 160 161 由于CRuntimeClass对象是static成员变量,因此需要在类外初始化。如果忘记初始化将会报链接错误。CRuntimeClass*CRuntimeClass:pFirstClass=NULL;建好了类类型路表,要实现IsKindOf功能很容易。首先在CObject加上一个IsKindOf函数,于是所有继承自此类的类都具有类型识别的功能。能够将某个CRuntimeClass对象与类类型型录中的元素进行比较。如: cpp view plaincopy162 class CObject 163 164 165

14、166 public: 167 168 bool IsKindOf(const CRuntimeClass*pClass)const 169 170 171 172 CRuntimeClass *pClassThis=GetRuntimeClass(); 173 174 while(pClassThis) 175 176 177 178 if(pClassThis=pClass) 179 180 return true; 181 182 pClassThis=pClassThis-m_pBaseClass;/沿着基类寻找。 183 184 185 186 return false; 187 1

15、88 189 190 ; 如果我们调用CWnd *cw=new CWnd; cw-IsKindOf(RUNTIME_CLASS(CFrameWnd); RUNTIME_CLASS实际就是&CFrameWnd:classCFrameWnd,它就是CFrameWnd的static的CRuntimeClass类型成员。函数内利用GetRuntimeClass取得本类的CRuntimeClass对象的地址,即&CWnd:classCWnd,然后进行比较。因为每一类型共用一个static的CRuntimeClass对象,因此属于同于类的CRuntimeClass对象的地址相同。动态创建 每一类的构建函数

16、可以记录在类型别录中,当获得一个类名称,通过查找类别型录表找出对应的元素,然后调用其构建函数产生新对象。 在CRuntimeClass中m_pfnCreateObject即为构建函数首地址。为了实现动态创建,需要添加两个宏:DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE。如:cpp view plaincopy191 #define DECLARE_DYNCREATE(class_name) 192 193 DECLARE_DYNCREATE(class_name) 194 195 static CObject *PASCAL CreateObject(); 196

17、 197 #define IMPLEMENT_DYNCREATE (class_name,base_class_name) 198 199 CObject*PASCAL class_name:CreateObject() 200 201 return new classname; 202 203 _IMPLEMENT_RUNTIMECLASS(class_name,base_class_name, 204 205 0xFFFF,class_name:CreateObject) 以CFrameWnd为例,下列程序代码:cpp view plaincopy206 class CFrameWnd:p

18、ublic CWnd 207 208 209 210 public: 211 212 DECLEARE_DYNCREATE(CFrameWnd); 213 214 ; IMPLEMENT_DYNCREATE(CFrameWnd,CWnd);展开如下: cpp view plaincopy215 class CFrame:public CWnd 216 217 218 219 public: 220 221 static CRuntimeClass classCFrameWnd; 222 223 virtual CRuntimeClass *GetRuntimeClass()const; 224

19、 225 static CObject *PASCAL CreateObject(); 226 227 ; 228 229 CObject _PASCAL CFrameWnd:CreateObject() 230 231 232 233 return new CFrameWnd; 234 235 236 static char _lpszCFrameWnd=CFrameWnd; 237 238 CRuntimeClass CFrameClass:classCFrameWnd= 239 240 _lpszCFrameWnd,sizeof(CFrameWnd),0xFFFF,CFrameWnd:C

20、reateObject,RUNTIME_CALSS(CWnd),NULL; 241 242 static AFX_CLASSINIT _init_CFrameWnd 243 244 (&CFrameWnd:classCFrameWnd); 245 246 CRuntimeClass*CFrameWnd:GetRunimeClass()const 247 248 return &CFrameWnd:classCFrameWnd; 注意对象构建函数为static函数。为了支持动态创建需要在CRuntimeClass内添加两个函数:CreateObject和CRuntimeClass:Load成员函

21、数。cpp view plaincopy249 CObject *CRuntimeClass:CreateObject() 250 251 252 253 If(m_pfnCreateObject=NULL)/不支持动态创建。 254 255 256 257 throw runtime_error(此类不支持动态创建); 258 259 Return NULL; 260 261 262 263 CObject*pObject=(*m_pfnCreateObject)(); 264 265 Return pObject; 266 267 268 269 CRuntimeClass*PASCL C

22、RuntimeClass:Load() 270 271 272 273 Char szClassName64; 274 275 CRuntimeClass*pClass 276 277 coutszClassName; 280 281 for(pClass=pFirstClass;pClass;pClass=pClass-m_pNextClass) 282 283 284 285 if(strcmp(szClassName,pClass-m_lpszClassName)=0) 286 287 return pClass; 288 289 return NULL; 290 291 292 293

23、 以下为类型识别及动态创建的完整代码:cpp view plaincopy294 #include 295 #include 296 #include 297 using namespace std; 298 299 class CObject; 300 class CRuntimeClass 301 302 public: 303 char* m_lpszClassName;/对象所属类名 304 int m_nObjectSize;/对象大小 305 int m_wSchema;/模式号 306 CObject*(PASCAL*m_pfnCreateObject)();/构建函数,抽象类为

24、NULL 307 CRuntimeClass *m_pBaseClasss;/基类CRuntimeClass对象指针。 308 static CRuntimeClass *pFirstClass;/链表头指针。static 309 CRuntimeClass *m_pNextClass;/下一指针。 310 public: 311 CObject*CreateObject() 312 313 if(m_pfnCreateObject=NULL) 314 315 cout该类型不支持动态创建!endl; 316 return NULL; 317 318 CObject*pClass=(*m_pf

25、nCreateObject)(); 319 return pClass; 320 321 static CRuntimeClass*Load() 322 323 couts; 326 for(CRuntimeClass*pClass=pFirstClass;pClass;pClass=pClass-m_pBaseClasss) 327 328 if(pClass-m_lpszClassName=s) 329 330 return pClass; 331 332 333 return NULL; 334 335 ; 336 337 class AFX_CLASSINIT 338 339 publ

26、ic: 340 AFX_CLASSINIT(CRuntimeClass*pNewClass)/构造函数 341 342 pNewClass-m_pNextClass=CRuntimeClass:pFirstClass; 343 CRuntimeClass:pFirstClass =pNewClass; 344 345 ; 346 347 /*/ 348 /* 动态类型识别宏定义 349 /与CRuntimeClass类中的构建函数相区别。此处的CreateObject函数在每个类中都以static成员函数存在,用以 350 /初始化类型型录表,而CRuntimeClass中的CreateObj

27、ect用于调用每个类的构建函数。仅仅是函数名相同罢了。*/ 351 /*/ 352 353 #define DECLARE_DYNAMIC(class_name) 354 public: 355 static CRuntimeClass Class#class_name; 356 virtual CRuntimeClass*GetRuntimeClass()const; 357 358 359 #define DECLARE_DYNCREATE(class_name) 360 DECLARE_DYNAMIC(class_name) 361 static CObject*PASCAL CreateObject(); 362 363 #define RUNTIME_CLASS(class_name) 364 (&class_name:Class#class_name) 365 366 #define _IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1