正文

MFC RTTI,DYNCREATE,SERIAL 技术相关宏分析2007-11-16 19:12:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/lingdlz/30945.html

分享到:

 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

阅读(3872) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册