MFC RTTI,DYNCREATE,SERIAL 技术相关宏分析 使用 MFC 的 RTTI 先直接或者间接从 CObject 类派生自己的类,如下 : =============================================================================== class MyClass : public CWnd{ int a;public: DECLARE_DYNMAIC(MyClass); }; INPLEMENT_DYNMIC(MyClass,CWnd); MyClass t;if(t.IsKindOf(RUNTIME_CLASS(CObject))) MessageBox(NULL,"fdk","fdkf",MB_OK); =============================================================================== 一: DECLARE_DYNMAIC(MyClass) 的宏扩展: #ifdef _AFXDLL // 动态链接版#define DECLARE_DYNAMIC(class_name) \protected: \ static CRuntimeClass* PASCAL _GetBaseClass(); \public: \ static const AFX_DATA CRuntimeClass class##class_name; \ virtual CRuntimeClass* GetRuntimeClass() const; \ #define _DECLARE_DYNAMIC(class_name) \protected: \ static CRuntimeClass* PASCAL _GetBaseClass(); \public: \ static AFX_DATA CRuntimeClass class##class_name; \ virtual CRuntimeClass* GetRuntimeClass() const; \ #else // 静态链接版#define DECLARE_DYNAMIC(class_name) \public: \ static const AFX_DATA CRuntimeClass class##class_name; \ virtual CRuntimeClass* GetRuntimeClass() const; \ #define _DECLARE_DYNAMIC(class_name) \public: \ static AFX_DATA CRuntimeClass class##class_name; \ virtual CRuntimeClass* GetRuntimeClass() const; \ #endif 这里我们只分析动态链接版的:#define DECLARE_DYNAMIC(class_name) \protected: \ static CRuntimeClass* PASCAL _GetBaseClass(); \public: \ static const AFX_DATA CRuntimeClass class##class_name; \ virtual CRuntimeClass* GetRuntimeClass() const; \ 于是:class MyClass : public CWnd{ int a;public: DECLARE_DYNMAIC(MyClass); }; 扩展为:class MyClass : public CWnd{ int a;public: protected: static CRuntimeClass* PASCAL _GetBaseClass(); public: static const AFX_DATA CRuntimeClass classMyClass; virtual CRuntimeClass* GetRuntimeClass() const; }; =============================================================================== 二: INPLEMENT_DYNMIC(MyClass,CWnd) 的宏扩展: #define IMPLEMENT_DYNAMIC(class_name, base_class_name) \ IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, NULL) #ifdef _AFXDLL // 动态链接版#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \ CRuntimeClass* PASCAL class_name::_GetBaseClass() \ { return RUNTIME_CLASS(base_class_name); } \ AFX_COMDAT const AFX_DATADEF CRuntimeClass class_name::class##class_name = { \ #class_name, sizeof(class class_name), wSchema, pfnNew, \ &class_name::_GetBaseClass, NULL }; \ CRuntimeClass* class_name::GetRuntimeClass() const \ { return RUNTIME_CLASS(class_name); } \ #define _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \ CRuntimeClass* PASCAL class_name::_GetBaseClass() \ { return RUNTIME_CLASS(base_class_name); } \ AFX_COMDAT AFX_DATADEF CRuntimeClass class_name::class##class_name = { \ #class_name, sizeof(class class_name), wSchema, pfnNew, \ &class_name::_GetBaseClass, NULL }; \ CRuntimeClass* class_name::GetRuntimeClass() const \ { return RUNTIME_CLASS(class_name); } \ #else // 静态链接版#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \ AFX_COMDAT const AFX_DATADEF CRuntimeClass class_name::class##class_name = { \ #class_name, sizeof(class class_name), wSchema, pfnNew, \ RUNTIME_CLASS(base_class_name), NULL }; \ CRuntimeClass* class_name::GetRuntimeClass() const \ { return RUNTIME_CLASS(class_name); } \ #define _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \ AFX_DATADEF CRuntimeClass class_name::class##class_name = { \ #class_name, sizeof(class class_name), wSchema, pfnNew, \ RUNTIME_CLASS(base_class_name), NULL }; \ CRuntimeClass* class_name::GetRuntimeClass() const \ { return RUNTIME_CLASS(class_name); } \ #endif 这里我们选 "动态链接"版的: #define IMPLEMENT_DYNAMIC(class_name, base_class_name) \ IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, NULL) #define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \ CRuntimeClass* PASCAL class_name::_GetBaseClass() \ { return RUNTIME_CLASS(base_class_name); } \ AFX_COMDAT const AFX_DATADEF CRuntimeClass class_name::class##class_name = { \ #class_name, sizeof(class class_name), wSchema, pfnNew, \ &class_name::_GetBaseClass, NULL }; \ CRuntimeClass* class_name::GetRuntimeClass() const \ { return RUNTIME_CLASS(class_name); } \ INPLEMENT_DYNMIC(MyClass,CWnd) 宏扩展后为(为了便于分析格式经过纠正): CRuntimeClass* PASCAL class_name::_GetBaseClass() { return RUNTIME_CLASS(CWnd);} AFX_COMDAT const AFX_DATADEF CRuntimeClass MyClass::classMyClass = { "MyClass", sizeof(class MyClass), 0xFFFF, NULL, &MyClass::_GetBaseClass, NULL }; CRuntimeClass* class_name::GetRuntimeClass() const { return RUNTIME_CLASS(MyClass);} ===============================================================================于是:class MyClass : public CWnd{ int a;public: DECLARE_DYNMAIC(MyClass); }; INPLEMENT_DYNMIC(MyClass,CWnd); MyClass t;if(t.IsKindOf(RUNTIME_CLASS(CObject))) MessageBox(NULL,"fdk","fdkf",MB_OK); 扩展为 : class MyClass : public CWnd{ int a;public: protected: static CRuntimeClass* PASCAL _GetBaseClass(); public: static const AFX_DATA CRuntimeClass classMyClass; virtual CRuntimeClass* GetRuntimeClass() const; }; CRuntimeClass* PASCAL class_name::_GetBaseClass() { return RUNTIME_CLASS(CWnd);} AFX_COMDAT const AFX_DATADEF CRuntimeClass MyClass::classMyClass = { "MyClass", sizeof(class MyClass), 0xFFFF,NULL, &MyClass::_GetBaseClass, NULL }; CRuntimeClass* class_name::GetRuntimeClass() const { return RUNTIME_CLASS(MyClass);} MyClass t;if(t.IsKindOf(RUNTIME_CLASS(CObject))) MessageBox(NULL,"fdk","fdkf",MB_OK); =============================================================================== 上面还有宏: RUNTIME_CLASS 该宏的定义为 #define RUNTIME_CLASS(class_name) ((CRuntimeClass*)(&class_name::class##class_name))于是RUNTIME_CLASS(CWnd) 扩展为: ((CRuntimeClass*)(&MyClass::classMyClass)) 到这里应该亮一下 : CRuntimeClass 结构了 struct CRuntimeClass{// Attributes LPCSTR m_lpszClassName; int m_nObjectSize; UINT m_wSchema; // schema number of the loaded class CObject* (PASCAL* m_pfnCreateObject)(); // NULL => abstract class #ifdef _AFXDLL // 动态链接版 CRuntimeClass* (PASCAL* m_pfnGetBaseClass)();#else // 静态链接版 CRuntimeClass* m_pBaseClass;#endif // Operations CObject* CreateObject(); // 这个是用于动态创建的 BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const; // Implementation void Store(CArchive& ar) const; // 这两个用于永久保存 static CRuntimeClass* PASCAL Load(CArchive& ar, UINT* pwSchemaNum); // CRuntimeClass objects linked together in simple list CRuntimeClass* m_pNextClass; // linked list of registered classes}; // 我们这里用动态版的及为: truct CRuntimeClass{ LPCSTR m_lpszClassName; // 类名 int m_nObjectSize; // 类大小 UINT m_wSchema; // 版本,是否可以 serial CObject* (PASCAL* m_pfnCreateObject)(); // 函数指针,用于DYNCREATE CRuntimeClass* (PASCAL* m_pfnGetBaseClass)(); // 函数指针,取父类的结构体 CRuntimeClass* m_pNextClass; // 链接下一个结构体 // 下面的都是函数了 CObject* CreateObject(); BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const; void Store(CArchive& ar) const; static CRuntimeClass* PASCAL Load(CArchive& ar, UINT* pwSchemaNum); }; ===============================================================================好了分析完了,最终的扩展结果是这样的: { 添加了点注释 }===============================================================================class MyClass : public CWnd{ int a;public: protected: static CRuntimeClass* PASCAL _GetBaseClass(); public: static const AFX_DATA CRuntimeClass classMyClass; virtual CRuntimeClass* GetRuntimeClass() const; }; CRuntimeClass* PASCAL class_name::_GetBaseClass() { // 返回指向父类的 CRuntimeClass 结构体指针 return (CRuntimeClass*)(&MyClass::classMyClass);} // 填充 CRuntimeClass 结构体,共六个数据成员,这里因为是结构体 // 数据成员都是 public 的,因此可以直接填充...AFX_COMDAT const AFX_DATADEF CRuntimeClass MyClass::classMyClass = { "MyClass", sizeof(class MyClass), 0xFFFF, NULL, &MyClass::_GetBaseClass, NULL }; CRuntimeClass* class_name::GetRuntimeClass() const { // 返回指向 MyClass 类数据成员 classMyClass 的指针 return (CRuntimeClass*)(&MyClass::classMyClass);} MyClass t; // IsKingOf() 是 CObject 类的成员,在 CObject 里实现if(t.IsKindOf(((CRuntimeClass*)(&CObject::classCObject))) MessageBox(NULL,"fdk","fdkf",MB_OK); 相信这些代码大家能够理解,我个人认为有必要弄懂这些宏,知道了 RTTI ,其它的那两个就非常容易理解了....... 江南孤峰 ///////// 2007--11--16

评论