




已阅读5页,还剩16页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
软件英才网 软件行业驰名招聘网站第三章:MFC六大关键技术之仿真:类型识别 深入理解MFC的内部运行原理,是本次学习深入浅出MFC的主要目的。要模仿的六大技术包括:1:MFC程序的初始化过程。2:RTTI(Runtime type identification)运行时类型识别。3:Dynamic creation 动态创建4:Persistence永久保存5:消息映射6:消息传递。RTTI(运行时类型识别) IsKindOf能够侦测某个对象是否属于某种类。即判断某一对象所属的类是否是父类或当前类; 要达到动态类型识别的能力,必须在构建类继承体系时记录必要的信息,这被称为类型型录表。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;/基类CRuntimeClass对象指针。 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 ( class_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()const; 以上代码仅仅是在类中定义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,NULL); 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 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: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 87 ; 用法: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 CRuntimeClass*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 &CWnd: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 ; 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 159 return &CObject:classCObject; 160 161 由于CRuntimeClass对象是static成员变量,因此需要在类外初始化。如果忘记初始化将会报链接错误。CRuntimeClass*CRuntimeClass:pFirstClass=NULL;建好了类类型路表,要实现IsKindOf功能很容易。首先在CObject加上一个IsKindOf函数,于是所有继承自此类的类都具有类型识别的功能。能够将某个CRuntimeClass对象与类类型型录中的元素进行比较。如: cpp view plaincopy162 class CObject 163 164 165 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 188 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对象的地址相同。动态创建 每一类的构建函数可以记录在类型别录中,当获得一个类名称,通过查找类别型录表找出对应的元素,然后调用其构建函数产生新对象。 在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 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:public 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 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:CreateObject,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成员函数。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 CRuntimeClass: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 以下为类型识别及动态创建的完整代码: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)();/构建函数,抽象类为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_pfnCreateObject)(); 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 public: 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中的CreateObject用于调用每个类的构建函数。仅仅是函数名相同罢了。*/ 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,wSchema,pfnNew) 367 class CRuntimeClass class_name:Class#class_name = 368 #class_name, 369 sizeof(class_name),wSchema,pfnNew,RUNTIME_CLASS(base_class_name),NULL; 370 static AFX_CLASSINIT _init#class_name( RUNTIME_CLASS(class_name); 371 CRuntimeClass *class_name:GetRuntimeClass()const 372 return &class_name:Class#class_name;/此处将class_name写成了classname花了一两天才查出来。啊啊啊啊啊。20120605 373 374 375 #define IMPLEMENT_DYNAMIC(class_name,base_class_name) 376 _IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,0xFFFF,NULL) 377 378 #define IMPLEMENT_DYNCREATE(class_name,base_class_name) 379 CObject*PASCAL class_name:CreateObject()return new class_name; 380 _IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,0xFFFF,class_name:CreateObject) 381 382 383 /*/ 384 /* 对CObject特殊处理。 */ 385 /*/ 386 class CObject 387 388 public: 389 CObject() 390 391 /coutCObject constructor!endl; 392 393 CObject() 394 395 /coutCObject destructor!m_pBaseClasss) 405 406 if(pThis=pClass) 407 408 return true; 409 410 411 return false; 412 413 ; 414 class CRuntimeClass CObject: ClassCObject= 415 416 CObject,sizeof(CObject),0xFFFF,NULL,NULL,NULL 417 ; 418 static AFX_CLASSINIT _init_CObject(&CObject: ClassCObject); 419 CRuntimeClass *CObject:GetRuntimeClass() 420 421 return &CObject:ClassCObject; 422 423 CRuntimeClass*CRuntimeClass:pFirstClass=NULL; 424 425 /*/ 426 /* */ 427 /*/ 428 class CCmdTarget:public CObject 429 430 DECLARE_DYNCREATE(CCmdTarget) 431 public: 432 CCmdTarget() 433 434 /coutCCmdTarget constructor!endl; 435 /CreateObject(); 436 437 CCmdTarget() 438 439 /coutCCmdTarget destructor!endl; 440 441 442 ; 443 IMPLEMENT_DYNCREATE(CCmdTarget,CObject) 444 445 446 ; 447 class CWnd:public CCmdTarget 448 449 DECLARE_DYNCREATE(CWnd) 450 public: 451 CWnd() 452 453 /coutCWnd constructorendl; 454 455 CWnd() 456 457 /coutCWnd destructorendl; 458 459 public: 460 virtual bool Create() 461 462 coutCWnd:Createendl; 463 CreateEx(); 464 return true; 465 466 bool CreateEx() 467 468 coutCWnd:CreateExendl; 469 PreCreateWindow(); 470 return true; 471 472 virtual bool PreCreateWindow() 473 474 coutCWnd:PreCreateWindowendl; 475 return true; 476 477 ; 478 IMPLEMENT_DYNCREATE(CWnd,CCmdTarget) 479 480 class CView :public CWnd 481 482 DECLARE_DYNCREATE(CView) 483 public: 484 CView() 485 486 /coutCView constructorendl; 487 488 489 CView() 490 491 /coutCView destructorendl; 492 493 494 ; 495 IMPLEMENT_DYNCREATE(CView,CWnd) 496 497 class CFrameWnd:public CWnd 498 499 DECLARE_DYNCREATE(CFrameWnd) 500 public: 501 CFrameWnd() 502 503 /coutCFrameWnd constructorendl; 504 505 506 CFrameWnd() 507 508 /coutCFrameWnd destructorendl; 509 510 public: 511 virtual bool Create() 512 513 coutCFrameWnd:Createendl; 514 CreateEx(); 515 return true; 516 517 virtual bool PreCreateWindow() 518 519 coutCFrameWnd:PreCreateWindowendl; 520 return true; 521 522 ; 523 IMPLEMENT_DYNCREATE(CFrameWnd,CWnd) 524 525 class CWinThread:public CCmdTarget 526 527 public: 528 CWinThread() 529 530 /coutCWinThread constructorendl; 531 532 CWinThread() 533 534 /coutCWinThread destructorendl; 535 536 public: 537 virtual bool InitInstance() 538 539 coutCWinThread:InitInstanceendl; 540 return true; 541 542 virtual bool Run() 543 544 coutCWinThread:Runendl; 545 return true; 546 547 ; 548 class CWinApp:public CWinThread 549 550 public: 551 CWinApp() 552 553 /coutCWinApp Constructor endl; 554 m_currentApp=this; 555 556 CWinApp() 557 558 /coutCWinApp destructor endl; 559 560 virtual bool InitApplication() 561 562 coutCWinApp:InitApplicationendl; 563 return true; 564 565 566 virtual bool InitInstan
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年合肥庐江县绣溪城市服务有限公司招聘2人考前自测高频考点模拟试题及答案详解参考
- 2025广东佛山市顺德区公办中小学招聘教师92人(编制)考前自测高频考点模拟试题及一套完整答案详解
- 2025湖南永州市零陵区第二批公开引进急需紧缺专业人才(医疗岗9人)模拟试卷及答案详解参考
- 安全培训教师含义课件
- 2025年后链轮项目合作计划书
- 2025江西南昌市青山湖区招聘社区工作者(专职网格员)45人模拟试卷及答案详解一套
- Indazole-Standard-生命科学试剂-MCE
- IID432-生命科学试剂-MCE
- H-PEG6-VH4127-NH2-生命科学试剂-MCE
- GS-6620-PM-1-Cyano-2-C-methyl-4-aza-7-9-dideaza-adenosine-生命科学试剂-MCE
- 手术部(室)医院感染控制标准WST855-2025解读课件
- 酒店法律培训课件
- 公证一般程序课件
- 2025年食品安全员考试题库(含答案)
- 口腔补牙课件
- 2025至2030年中国茄尼醇行业市场需求预测及投资战略规划报告
- 2025年四川省事业单位考试公共基础知识真题及答案解析
- 保障农民工工资课件
- 婴儿呛奶海姆立克急救法
- 扁桃体癌护理查房记录
- 壶腹部肿瘤的治疗及护理
评论
0/150
提交评论