MFC中的动态创建
1、为了能够动态创建,程序必须维护一个CRuntimeClass的类,当需要去识别一个类的时候,就依次去查找这个链表,而这个是通过一组宏来实现的。因为是一个链表,所以就需要初始化,这个初始化在CObject中用稍有不同的宏来实现的。
2、CRuntimeClass的结构:
LPCSTR m_lpszClassName //类名
int m_nObjectSize //类字节大小,不计算分配的内存
UINT m_wSchema //一般为0xFFFF
CObject* ( PASCAL* m_pfnCreateObject )( ) //一个函数指针,用来 动态创建对象
CRuntimeClass* ( PASCAL* m_pfn_GetBaseClass )( ) //如果是动态加载的话,就指向基类的CRuntimeClass对象的指针,否则为null
CRuntimeClass* m_pBaseClass //如果是静态加载的话,就指向基类的CRuntimeClass对象的指针,否则为null
CObject* CreateObject( ); //一个函数,用来创建类本身
BOOL IsDerivedFrom( const CRuntimeClass* pBaseClass) const;//一个函数,用来判断是否继承自某个类
3、这组宏就是DECLARE_DYNCREATE(class_name) 与 IMPLEMENT_DYNCREATE(class_name, base_class_name),其实在这组宏的内部还有一组宏,大家可以自己去查看,其实这里面的这组宏是来实现类型识别的。下面将展示将这组宏展开后的代码应该是如何的:
#define DECLARE_DYNCREATE(class_name)所对应的代码 protected: static CRuntimeClass* PASCAL _GetBaseClass(); public: static const CRuntimeClass class##class_name; static CRuntimeClass* PASCAL GetThisClass(); virtual CRuntimeClass* GetRuntimeClass() const; static CObject* PASCAL CreateObject(); #define IMPLEMENT_DYNCREATE(class_name, base_class_name)所对应的代码 CObject* PASCAL class_name::CreateObject() { return new class_name; } CRuntimeClass* PASCAL class_name::_GetBaseClass() { return RUNTIME_CLASS(base_class_name); } AFX_COMDAT const CRuntimeClass class_name::class##class_name = { #class_name, sizeof(class class_name), wSchema, pfnNew, &class_name::_GetBaseClass, NULL, class_init }; CRuntimeClass* PASCAL class_name::GetThisClass() { return _RUNTIME_CLASS(class_name); } CRuntimeClass* class_name::GetRuntimeClass() const { return _RUNTIME_CLASS(class_name); } 假如这里有一个CView类 则 #define DECLARE_DYNCREATE(CView)对应的翻译后的代码为: protected: //其中PASCAL是调用协议,此处声明了一个函数。 static CRuntimeClass* PASCAL _GetBaseClass(); public: //此处声明一个CRuntimeClass的对象,来保存相应的类信息 static const CRuntimeClass classCView; //声明一个获得类本身的信息的一个函数 static CRuntimeClass* PASCAL GetThisClass(); //声明一个获得CRuntimeClass的结构 virtual CRuntimeClass* GetRuntimeClass() const; //声明一个可以动态创建类本身的函数 static CObject* PASCAL CreateObject(); #define IMPLEMENT_DYNCREATE(CView, CWnd)所对应翻译后的代码为: //创建类本身的对象 CObject* PASCAL CView::CreateObject() { return new CView; } //获得基类的信息 CRuntimeClass* PASCAL CView::_GetBaseClass() { return RUNTIME_CLASS(base_class_name); } //声明一个结构对象,并初始化 AFX_COMDAT const CRuntimeClass CView::classCView = { "CView", sizeof(class CView), 0xFFFF, CView::CreateObject, &CView::_GetBaseClass, NULL, class_init }; //获得该类的相应信息 CRuntimeClass* PASCAL CView::GetThisClass() { return _RUNTIME_CLASS(CView); } 获得该类的相应信息 CRuntimeClass* class_name::GetRuntimeClass() const { return _RUNTIME_CLASS(CView); }