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里面添加自己创建对象的函数指针. 然后自己的类中实现这个函数.创建自己的对象并且返回
这个就是动态创建了.