[MFC] RTTI应用总结(一)

[MFC] RTTI应用总结(一)

MFC 六大机制之RTTI——动态创建类

概念介绍

RTTI (Runtime Type Identification)

MFC CObject 为基类,通过动态生成类机制完成了一整套MFC类的派生

使用CRunTimeClass类来实现整个动态的创建过程。

本文在Visual Studio 2013 + Windows7 环境下进行 MFC 应用程序的举例

CObject类介绍

CObject是大多数MFC类的根类或基类CObject类有很多有用的特性:对运行时类信息的支持,对动态创建的支持,对串行化的支持,对象诊断输出,等等。MFCCObject派生出许多类,具备其中的一个或者多个特性。程序员也可以从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出来的指向对象的指针,所以在后面要对接收这个指针的pObjdelete处理,否则,不释放该部分内存会导致内存泄漏哦.

LL的话:对于动态创建类的这部分知识,我只是粗浅地介绍了一下,欢迎补充和指导,文章中有什么问题和错误,请不吝指出,谢谢!

参考:说说MFC中CRuntimeClass和CObject之间的那点事

猜你喜欢

转载自blog.csdn.net/llwodao/article/details/78121268
MFC
今日推荐