MFC RTTI 探究

MFC RTTI 探究

张杰

2011-09-17

声明

本文由张杰原创,参考了侯杰先生的《深入浅出MFC》,源码摘自 Microsoft Visual Studio 9.0\VC。 

个人能力有限,文章必定存在很多错误。我的邮箱是:chinajiezhang@gmail.com chinajiezhang@163.com  欢迎您来邮件斧正。当然您也可以加我 msn: chinazhangjie@hotmail.com 交流。

本文可供传播、交流、学习使用,但请不要用于商业用途。转载请标明此声明,谢谢您的合作。

DECLARE_DYNCREATE 和 IMPLEMENT_DYNCREATE

查看DECLARE_DYNCREATE 定义(c:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\include\afx.h

#define DECLARE_DYNCREATE(class_name) \

DECLARE_DYNAMIC(class_name) \

static CObject* PASCAL CreateObject();

查看DECLARE_DYNAMIC定义(c:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\include\afx.h):

#define DECLARE_DYNAMIC(class_name) \

protected: \

static CRuntimeClass* PASCAL _GetBaseClass(); \

public: \

static const CRuntimeClass class##class_name; \

static CRuntimeClass* PASCAL GetThisClass(); \

virtual CRuntimeClass* GetRuntimeClass() const; \

不再有宏了,我们找个例子将代码展开看看效果(创建 MFC 单文档,命名为:FirstMFCDemo):

FirstMFCDemoDoc.h下有行代码:

DECLARE_DYNCREATE(CFirstMFCDemoDoc)

展开代码为:

protected: 

static CRuntimeClass* PASCAL _GetBaseClass(); 

public: 

static const CRuntimeClass classCFirstMFCDemoDoc; 

static CRuntimeClass* PASCAL GetThisClass(); 

virtual CRuntimeClass* GetRuntimeClass() const; 

static CObject* PASCAL CreateObject();

先不管代码的具体含义,把 IMPLEMENT_DYNCREATE 宏定义看了再说(c:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\include\afx.h):

#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定义(c:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\include\afx.h):

#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew, class_init) \

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); }

查看RUNTIME_CLASS_RUNTIME_CLASS宏定义:

#define RUNTIME_CLASS(class_name) \

                      (class_name::GetThisClass())

#define _RUNTIME_CLASS(class_name) \

         ((CRuntimeClass*)(&class_name::class##class_name))

 FirstMFCDemoDoc.cpp 找到代码:

IMPLEMENT_DYNCREATE(CFirstMFCDemoDoc, CDocument)

展开后为:

CObject* PASCAL CFirstMFCDemoDoc::CreateObject() \

{ return new CFirstMFCDemoDoc; } \

CRuntimeClass* PASCAL CFirstMFCDemoDoc::_GetBaseClass() \

{ return CDocument::GetThisClass(); } \

AFX_COMDAT const CRuntimeClass CFirstMFCDemoDoc::classCFirstMFCDemoDoc = { 

#CFirstMFCDemoDoc, sizeof(class CFirstMFCDemoDoc), 0xFFFF, CFirstMFCDemoDoc::CreateObject, \

&CFirstMFCDemoDoc::_GetBaseClass, NULL, NULL }; \

CRuntimeClass* PASCAL CFirstMFCDemoDoc::GetThisClass() \

{ return (CRuntimeClass*)(&CFirstMFCDemoDoc::classCFirstMFCDemoDoc); } \

CRuntimeClass* CFirstMFCDemoDoc::GetRuntimeClass() const \

{ return (CRuntimeClass*)(&CFirstMFCDemoDoc::classCFirstMFCDemoDoc); }

好乱的团代码啊,我们来理理:

DECLARE_DYNCREATE 和 IMPLEMENT_DYNCREATE为类 CFirstMFCDemoDoc 添加了3个静态函数1个虚函数1静态CRuntimeClass 类型常量,以及代码实现体。分别为:

public:

virtual

CObject* PASCAL CFirstMFCDemoDoc::CreateObject() 

{

return new CFirstMFCDemoDoc;

}

protected:

static

CRuntimeClass* PASCAL CFirstMFCDemoDoc::_GetBaseClass() 

return CDocument::GetThisClass(); 

static

AFX_COMDAT const CRuntimeClass 

CFirstMFCDemoDoc::classCFirstMFCDemoDoc = { 

#CFirstMFCDemoDoc, 

sizeof(class CFirstMFCDemoDoc), 

0xFFFF, 

CFirstMFCDemoDoc::CreateObject, 

&CFirstMFCDemoDoc::_GetBaseClass,

NULL, 

NULL 

}; 

CRuntimeClass* PASCAL CFirstMFCDemoDoc::GetThisClass() 

return(CRuntimeClass*)(&CFirstMFCDemoDoc::classCFirstMFCDemoDoc); 

CRuntimeClass* CFirstMFCDemoDoc::GetRuntimeClass() const 

return(CRuntimeClass*)(&CFirstMFCDemoDoc::classCFirstMFCDemoDoc); 

}

想要知道这些代码到底在干什么,就必须了解 CRunTimeClass 是干什么的?废话不说,直接上 CRuntimeClass 源码(c:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\include\afx.h

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;

// dynamic name lookup and creation

static CRuntimeClass* PASCAL FromName(LPCSTR lpszClassName);

static CRuntimeClass* PASCAL FromName(LPCWSTR lpszClassName);

static CObject* PASCAL CreateObject(LPCSTR lpszClassName);

static CObject* PASCAL CreateObject(LPCWSTR lpszClassName);

// 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

const AFX_CLASSINIT* m_pClassInit;

};

查看 AFX_CLASSINIT 类型定义:

struct AFX_CLASSINIT

{ AFX_CLASSINIT(CRuntimeClass* pNewClass) { AfxClassInit(pNewClass); } };

继续查看 AfxClassInit 定义:

void AFXAPI AfxClassInit(CRuntimeClass* pNewClass)

{

AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

AfxLockGlobals(CRIT_RUNTIMECLASSLIST);

pModuleState->m_classList.AddHead(pNewClass);

AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);

}

由此看出,AFX_CLASSINIT结构完成了链表的链接操作,我们不做深究。

MFC 每个类基本都有一个 CRuntimeClass 类型的对象,这些对象构成了一个链表。链表的头是谁呢?答案是CObject,它是MFC所有类的祖先类。这个链表记录了类的名称、链表的Next指针、类的基类指针等等操作。我们可以用这些记录来比较, 以达到 RTTI 的能力。

我百度了几张图片(事实上,这是《深入浅出MFC》中的图片,至少长的很像,O(_)O~,便于理解 RTTI 


好吧,就讲到这里了。能力有限,再深也就看你们的了。

posted @ 2011-09-20 00:37  独酌逸醉  阅读(1703)  评论(0编辑  收藏  举报