说说MFC中CRuntimeClass和CObject之间的那点事 (2)
DECLARE_DYNAMIC宏与DECLARE_DYNCREATE宏
在1当中看到了DECLARE_DYNAMIC的源码实现,DECLARE_DYNCREATE及对应的IMPLEMENT_DYNCREATE宏源码如下:
// not serializable, but dynamically constructable #define DECLARE_DYNCREATE(class_name) \ DECLARE_DYNAMIC(class_name) \ static CObject* PASCAL CreateObject();
#define IMPLEMENT_DYNCREATE(class_name, base_class_name) \
CObject* PASCAL class_name::CreateObject() \
{ return new class_name; } \
IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, \
class_name::CreateObject, NULL)
可见,“DYNCREATE” 不仅包含了“DYNAMIC”,而且多了一样很重要的东西,那就是静态函数CreateObject()。在声明了这样一个函数后,该类就能支持“动态”对象创建,但是前提是类必须有默认的构造函数,这可以从 CreateObject的实现中看出来,它仅仅是创建并返回了一个类对象。
这样,与CRuntimeClass相结合使用,就可以动态的创建对象。这里所谓的动态,我的理解是指不需要用户自己编码去创建,而是由MFC框架去创建。比如在单文档视图中:
pDocTemplate = new CSingleDocTemplate( IDR_MAINFRAME, RUNTIME_CLASS(CMSMoneyDemoDoc), RUNTIME_CLASS(CMainFrame), // main SDI frame window RUNTIME_CLASS(CMSMoneyDemoView)); AddDocTemplate(pDocTemplate);
上面的代码中, RUNTIME_CLASS(class_name)便是返回了相应的类的CRuntimeClass静态变量,然后从上一篇中可知,这个CRuntimeClass类型的静态变量中包含了其对应的类的名字,并且其本身实现了一个CreateObject函数,这样,CRuntimeClass静态变量便可以根据其本身的信息来动态创建一个其所属者的对象。这便是为啥MFC框架通过上面类似的文档模板代码自动为我们创建了Mainframe、doc以及view了,因此在MFC 的doc-view结构中,我们并不需要自己去显示创建主窗口、文档和视图,这些都由文档模板类去完成了。文档模板类的主要作用就是将这三者联系起来。