MFC原理第四讲.动态创建机制

2019-05-25 16:47:20 浏览数 (1)

              MFC原理第四讲.动态创建机制

一丶要学习的知识点以及简介

  动态创建是什么意思?

    动态创建其实就是跟C 的new一样.都是创建对象.但是规避了C 语法的缺陷.

例如:

    char * ClassName = "CMyApp"

    CObject *obj = new ClassName;

C 中不允许这样编写代码

要学习的知识点

    1.DECLARE_DYNCREATE 宏 学过上讲RTTI的应该明白.这个就是个文字替换. 也可以说这个宏是一个声明宏 当然也有实现宏

    2.IMPLEMENT_DYNCREATE

还需要了解CRuntimeClass 结构. 支持动态创建的成员.

代码语言:javascript复制
struct CRuntimeClass
{

    LPCSTR m_lpszClassName;              类名
    int m_nObjectSize;                         类大小
    UINT m_wSchema;                        类编号
    CObject* (PASCAL* m_pfnCreateObject)(); 存放支持动态创建的类

    CRuntimeClass* m_pBaseClass;


// Operations
    CObject* CreateObject();                          动态创建函数
    BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const; 判断函数

    ...
    CRuntimeClass* m_pNextClass;       链表存储执向下一个
    
};

二丶如何使用动态创建.

  支持动态创建的是跟窗口有关的. 也就是CFrameWnd类. 如果我们继承了这个类.我们也可以让他支持动态创建.

  1.添加声明宏

  2.添加实现宏

  3.动态创建使用.

添加声明宏 则添加到我们继承CFrameWnd类中即可. 实现宏则在外边

参数填写自己的类名

添加实现宏

使用动态创建. 在InitInstance里面使用即可.我们的new 窗口改成动态创建即可.

RUNTIME_CLASS宏可以拆解开.

代码语言:javascript复制
m_pMainWnd = (CMainWnd *)((CRuntimeClass*)(&CMainWnd::classCMainWnd))->CreateObject();

应用程序实现截图:

三丶动态创建实现原理 之 宏 拆开

   我们要看实现原理.当然要把宏拆看看看做了什么事情了.

1. DECLARE_DYNCREATE 宏拆开

代码语言:javascript复制
#define DECLARE_DYNCREATE(class_name) 
    DECLARE_DYNAMIC(class_name)                  RTTI动态识别
    static CObject* PASCAL CreateObject();

我们可以看到这个宏 包含了我们的RTTI 类型识别. 并且添加了一个新的 成员函数

static Cobject * Createobject();

RTTI动态识别.上一讲已将讲过了. 就是添加了一个 CRuntimeClass 成员.以及获取成员的方法. 本次不讲解.

全部解开的宏

代码语言:javascript复制
public: 
    static const CRuntimeClass classCMainWnd;          指针
    virtual CRuntimeClass* GetRuntimeClass() const;  获取这个指针的函数


    static CObject* PASCAL CreateObject();   新增的函数

2.实现宏拆开 IMPLEMENT_DYNCREATE

代码语言:javascript复制
#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_RUNTIMECLASS  
也进行拆开.
#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew, class_init) 
    AFX_COMDAT const CRuntimeClass class_name::class##class_name = { 
        #class_name, sizeof(class class_name), wSchema, pfnNew, 
            RUNTIME_CLASS(base_class_name), NULL, class_init }; 
    CRuntimeClass* class_name::GetRuntimeClass() const 
        { return RUNTIME_CLASS(class_name); }

第一个宏 IMPLEMENT_DYNCREATE 其实就是对 CreateObject进行实现. 也就是返回自己本身的 创建的类

第二个宏就是对 自己本身的结构体成员进行初始化.并且实现虚函数获取自己的这个成员. 跟RTTI一样.只不过初始化的时候.结构体初始化的值不一样.也就是我们上面说的CRuntimeClass结构中的新增的两个

成员进行了赋值.

解析的代码

代码语言:javascript复制
//IMPLEMENT_DYNCREATE(CMainWnd,CFrameWnd)

CObject* PASCAL CMainWnd::CreateObject() 
{
    return new CMainWnd;
} 

const CRuntimeClass CMainWnd::classCMainWnd = 
    { 
        "CMainWnd", sizeof(class CMainWnd), 0xFFFF, CMainWnd::CreateObject,  添加了自己的成员函数指针.其余地方一样 这个函数指针创建自己本身对象并且返回.
        RUNTIME_CLASS(CFrameWnd), NULL, NULL 
    }; 
CRuntimeClass* CMainWnd::GetRuntimeClass() const 
{ 
    return RUNTIME_CLASS(CMainWnd);
}

所以远离就是CRuntime里面添加自己创建对象的函数指针. 然后自己的类中实现这个函数.创建自己的对象并且返回

这个就是动态创建了.

0 人点赞