[MFC] RTTI应用总结(一)
MFC 六大机制之RTTI——动态创建类
概念介绍
RTTI
(Runtime Type Identification)
MFC
CObject 为基类,通过动态生成类机制完成了一整套MFC类的派生使用CRunTimeClass类来实现整个动态的创建过程。
本文在Visual Studio 2013 + Windows7 环境下进行 MFC 应用程序的举例
CObject类介绍
CObject
是大多数MFC
类的根类或基类。CObject
类有很多有用的特性:对运行时类信息的支持,对动态创建的支持,对串行化的支持,对象诊断输出,等等。MFC
从CObject
派生出许多类,具备其中的一个或者多个特性。程序员也可以从CObject
类派生出自己的类,利用CObject
类的这些特性。注意:
CObject
类不支持多继承。派生的类仅仅拥有一个CObject
基类,并且CObject
在等级体系中必须位于最左边。不过,它也允许在多继承分支的右边有其结构及非CObject
派生类。
来自msdn:
Members:
Protected Constructors
Name Description CObject::CObject Default constructor.
Public Methods
Name Description CObject::AssertValid Validates this object’s integrity. CObject::Dump Produces a diagnostic dump of this object. CObject::GetRuntimeClass Returns the CRuntimeClass structure corresponding to this object’s class. CObject::IsKindOf Tests this object’s relationship to a given class. CObject::IsSerializable Tests to see whether this object can be serialized. CObject::Serialize Loads or stores an object from/to an archive.
Public Opreators
Name Description CObject::operator delete Special delete operator. CObject::operator new Special new operator.
示例
动态创建类
动态创建
顾名思义—只有在使用时创建 ,CObject
中的提供了一个CRuntimeClass
的类 , 和对应的宏。而在实际的编程中, 主要是通过宏
DECLARE_DYNCREATE
以及IMPLEMENT_DYNCREATE
来提供和支持动态类创建的方法。要想一下子明白动态类的原理比较困难,所以我们先从它的表象—实现的方法来看。
为此,我们来创建一个基于对话框的简单Demo,再加入两个对话框类,以体现一个需要动态创建类的模型。
旧 : 每用一个
Dialog
都去申请它的对象,并逐个执行。
void CDemoDlg::OnBnClickedButton1() { CDialog1 dlg; dlg.DoModal(); } void CDemoDlg::OnBnClickedButton2() { CDialog2 dlg; dlg.DoModal(); }
实现了两个模式对话框类的创建和对话框生成,但当需要创建多个对话框时,这种方式远远无法达到我们想要的效果。
新 : 想要哪一个对话框就申请和生成哪一个,比如下面的这种方式
void CDemoNewDlg::OnBnClickedButton1() { CString strDlgNo; //获取需要生成的窗口编号 m_ctlDlgNum.GetWindowText(strDlgNo); long class_no = atoi(strDlgNo); //创建类名与对应键值 map<int, string> ClassMap; ClassMap.insert(make_pair(1, "CDialog1")); ClassMap.insert(make_pair(2, "CDialog2")); //加载动态运行类 map<string, CRuntimeClass*> RunClassMap; RunClassMap.insert(make_pair("CDialog1", RUNTIME_CLASS(CDialog1))); RunClassMap.insert(make_pair("CDialog2", RUNTIME_CLASS(CDialog2))); string class_name = ClassMap[class_no]; //动态生成对应CObject类 CObject* pObj = RunClassMap[class_name]->CreateObject(); //检查是否创建成功 ASSERT(pObj->IsKindOf(RunClassMap[class_name])); //生成对话框 CDialogEx* pDlg = (CDialogEx *)pObj; pDlg->DoModal(); //清理和回收内存 RunClassMap.empty(); delete pObj; }
当其中的一些步骤被拆分开,并实现成外部的配置项,我们就得到了真正的动态创建的全过程。
关于动态创建的类的回收
//清理和回收内存 RunClassMap.empty(); delete pObj;
为什么要在这里使用
delete
呢?因为:
#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)
IMPLEMENT_DYNCREATE
这个宏被定义成了一个一串带有CreateObject()
的函数,它的返回值是一个new
出来的指向对象的指针,所以在后面要对接收这个指针的pObj
做delete
处理,否则,不释放该部分内存会导致内存泄漏哦.
LL的话:对于动态创建类的这部分知识,我只是粗浅地介绍了一下,欢迎补充和指导,文章中有什么问题和错误,请不吝指出,谢谢!