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

理解“MFC的动态类型识别和动态创建”

2013年01月28日 ⁄ 综合 ⁄ 共 1456字 ⁄ 字号 评论关闭

我们写MFC程序的时候,要做的工作通常就是改写从几大基类继承来的派生类内容,加一些变量啦,加一些函数啦,改一些函数行为啦;或者再多派生一些类,再在新派生出来的类内部重复刚才提到的那些事。可是我们从来不会写

CMyDoc myDoc;

或者

CMyView myView;

之类的语句,也就是说我们从来没有把我们辛辛苦苦改好的类进行实例化。没有实例化又如何工作呢?当然这些类最终是要实例化成对象的,就是程序运行时候那一个个的窗口啊,编辑框啊等等。但是这些都是MFC帮我们做的,即不需要我们用代码写出来。那是不是MFC自动帮我们生成了这些用于实例化的代码呢?也不是,MFC就是想也没有这个能力,因为在代码编辑期它并不知道我们会怎样改写和怎么创建我们需要的类,也就是说MFC并没有这些类的信息,自然就无法创建。那怎么办?

当我们完成代码编辑之时,我们所需要的一切类的信息就确定了,而代码编辑之后的剩余步骤就是编译、链接和运行了。编译和链接都是为代码编写做后续工作。所以MFC真正有机会帮我们创建对象只能在运行期,就是所谓的动态创建。

可是运行期已经只剩下二进制代码了,MFC已经无法使用new这样的动作来执行创建了,所以MFC要想为我们动态创建对象,就必须具有运行期识别对象类型的能力,即所谓的RTTI(Runtime Type Information),如果在运行期能够知道要创建的对象的类型,稍作延伸,自然就可以进行该类型对象的创建了。

MFC采用这样的技术:定义一个叫做CRuntimeClass的类作为所有希望具有RTTI和动态创建能力的类的静态成员,当然包括从几大基类派生而来的类(CMyView啦,CMyDoc啦),然后维护一个CRuntimeClass对象的链表,这样就可以保存这些类的相关信息,并在运行时使用相关信息。比如CRuntimeClass类有如下成员:

m_lpszClassName //类名,通过对此成员的比较可以对RUNTIME_CLASS()宏和CObject::IsKindOf()函数提供支持
m_nObjectSize //类大小
m_pBaseClass //指向基类的CRuntimeClass对象,也是用于CObject::IsKindOf()的比对工作
m_pfnCreateObject //指向被描述类的创建函数(名为CreateObject(),非构造函数,但最终调用的仍然是构造函数),用于动态创建
CreateObject() //该函数内部利用m_pfnCreateObject()调用对应类的CreateObject()函数(同名,但不属于一个类,创建类中的CreateObject()单纯使用new创建对象)

还有其它成员没有列出。

有了这样的包含所有类的CRuntimeClass对象链表,就可以在运行时通过此链表得到类型信息和创建对象了,也就是可以RTTI和动态创建了——因为任何一个对象都有一个静态的CRuntimeClass成员。下面我们只要把修改过的类和新派生的类的信息加入这个链表就可以了,这项工作是通过几对宏来完成的,它们是:

DECLARE_DYNAMIC()/IMPLEMENT_DYNAMIC()
DECLARE_DYNCREATE()/IMPLEMENT_DYNCREATE()

宏做的工作就是为该类生成CRumtimeClass对象,完善该对象信息,并且将其加入链表。
MFC代码生成时,各个派生类自动带有这些宏,当程序员自己编码时如果想要具有RTTI和动态创建功能也应该写上这些宏。

抱歉!评论已关闭.