正文

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

阅读(3733) | 评论(0)


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

评论

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