现在的位置: 首页 > 综合 > 正文

MFC原理系列报告之:运行期类型识别

2013年07月22日 ⁄ 综合 ⁄ 共 1815字 ⁄ 字号 评论关闭

刚学习完MFC,一时心血来潮,分析下MFC的几个关键技术,算是对学习的总结。由于本人还是个初学者,能力有限,语言组织欠妥,肯定有不足之处,欢迎批评斧正。

 

有以下几个部分内容:

1.RTTI(运行期类型识别)

2.动态创建

3.序列化的实现

4.程序的产生,运行和结束 ,以单文档框架程序为例

5.单文档框架程序/类型之间的关系

6.MFC消息机制的流转

7.实现自己的SPY++

                                          二: RTTI, 动态创建,序列化

RTTI是动态创建的基础,序列化同时用到动态创建和RTTI,所以RTTI是MFC的基石。三者的关系很紧密。.

1.      动态创建可以简单理解为,通过字符串创建对象。比如你封装了一个类CLine,如何仅

仅通过字符串“CLine”创建来CLine类的对象。

2.      序列化是指从持久存储介质中读出或写入一个对象的过程。

 

举个例子:在一个CAD系统里,用户画了一些线条呀,矩形等等。如何将当前所有图形保存到文件中,下次打开文件,然后正确读取并显示出来。

让我们尝试分析下,假设有两个类CLine, CRectangle分别负责绘制线条和矩形。

CLine里保存线条的起始坐标点。

Crectangle保存矩形的左上角坐标点,以及右下角坐标点。

用户每画一个线条,则创建一个CLine对象,矩形也是如此。

当用户保存线条到文件时,需要保存哪些内容呢?肯定要有CLine的类型信息,类信息至少有类的名字。如果不保存,读取图形文件时,无法创建一个CLine对象,也就不能再正确显示出来。读出对象时,根据字符串“CLine”创建一个CLine对象,即动态创建。

这里保存和读取对象的过程就是序列化,很显然序列化需要动态创建的支持,但是二者共同基础却是RTTI。

                                            三. RTTI详解

RTTI (Run_Time Type Identification),即运行期类型识别,是MFC动态创建的基础,可以对类型进行管理,对类型之间的关系,对象的类型进行识别和检查。

RuntimeClass的结构体,所有具有RTTI和动态创建能力的类都需要添加一个CRuntimeClass静态成员,然后维护一个CRuntimeClass对象的链表,这样就可以保存这些类的相关信息,并在运行时使用相关信息。

MFC 里CRuntimeClass结构的的重要成员:

       LPCSTR m_lpszClassName;  //类名字符串

       int m_nObjectSize;               //对象大小

       UINT m_wSchema;             //被加载类的版本信息

       CObject* (PASCAL* m_pfnCreateObject)(); //指向动态创建对象函数的指针

       CRuntimeClass* m_pBaseClass;           //指向类的成员函数_GetBaseClass,返回基类CRuntimeClass

 

实现关键:

1.在主函数前,把每个支持RTTI的类都加一个该类型信息结构体对象赋值,通过静态成员变量实现的。

2.在结构体对象构造过程中,完成类型链表的构建,

3.通过IsKindOf,IsDerverFrom处理,遍历列表找到对应的类型。

 

本文手工模拟实现了一个运行期类型识别程序,

其中一份是宏定义实现的。手工模拟的CMyRunTimeClass

(为简化,只保存了最基本的类信息,参考附件)

 

链表完成构建后,对类型的查找,判断就很简单了。

以下是关键函数CMyRunTimeClass::IsDerivedFrom函数的实现:

 

//判断当前类是否从pBaseClass派生

bool CMyRunTimeClass::IsDerivedFrom(

const CMyRunTimeClass*pBaseClass)

{

  CMyRunTimeClass *pCurrent =this;

  while (pCurrent != NULL)

  {

    if (pCurrent ==pBaseClass)

    { return true; }

    //向上找父类的类型信息结构体对象

    pCurrent = pCurrent->m_pBaseClass;

  }

  return false;

}

抱歉!评论已关闭.