MFC中的RTTI是通过建立一个类别型录网来实现。MFC中基本上所有的类都是派生自CObject这个类,通过在所有的类中添加一个公有的静态成员类,这个类通过链表链接组成一个类别识别的链表,这个链表的最终节点指向CObject,由于是静态成员,因此在编译中实际上成为了一个全局变量,在初始化中就实现了这个链表的构建,不必创建任何一个类就实现了链表的构建和连接。这个类为CRuntimeClass。
struct CRuntimeClass
{
//Attributes
LPCSTR m_lpszClassName;
int m_nObjectSize;
UINT m_wSchema;
CObject* (PASCAL * m_pfnCreateObject)();
CRuntimeClass * m_pBaseClass;
CObject* CreateObject();
static CRuntimeClass * PASCAL Load();
//RuntimeClass link list
static CRuntimeClass * m_pFirstClass;
CRuntimeClass * m_pNextClass;
};
m_pFirstClass指向最后一个类,按照文件中类声明的顺序,及由基类到派生类的顺序,具体顺序如下。
以下是侯俊杰书中的MFC中RTTI和动态创建的仿真
//MFC.h
#define BOOL int
#define LPCSTR LPSTR
typedef char* LPSTR;
#define UINT int
#define PASCAL _stdcall
#define TRACE1 printf
#define TRUE 1
#define FALSE 0
#include <iostream>
#include <stdio.h>
#include<string.h>
class CObject;
struct CRuntimeClass
{
//Attributes
LPCSTR m_lpszClassName;
int m_nObjectSize;
UINT m_wSchema;
CObject* (PASCAL * m_pfnCreateObject)();
CRuntimeClass * m_pBaseClass;
CObject* CreateObject();
static CRuntimeClass * PASCAL Load();
//RuntimeClass link list
static CRuntimeClass * m_pFirstClass;
CRuntimeClass * m_pNextClass;
};
struct AFX_CLASSINIT
{
AFX_CLASSINIT(CRuntimeClass* pNewClass);
};
#define RUNTIME_CLASS(class_name) \
(&class_name::class##class_name)
#define DECLEAR_DYNAMIC(class_name) \
public: \
static CRuntimeClass class##class_name; \
virtual CRuntimeClass * GetRuntimeClass() const;
#define DECLARE_DYNCREATE(class_name) \
DECLEAR_DYNAMIC(class_name) \
static CObject * PASCAL CreateObject();
#define _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \
static char _lpsz##class_name[] = #class_name;\
CRuntimeClass class_name::class##class_name = { \
_lpsz##class_name, sizeof(class_name), wSchema, pfnNew, RUNTIME_CLASS(base_class_name), NULL}; \
static AFX_CLASSINIT _init_##class_name(&class_name::class##class_name); \
CRuntimeClass *class_name::GetRuntimeClass() const \
{ return &class_name::class##class_name;}
#define IMPLEMENT_DYNAMIC(class_name, base_class_name) \
_IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, NULL)
#define IMPLEMENT_DYNCREATE(class_name, base_class_name) \
CObject * class_name::CreateObject() \
{ return new class_name;} \
_IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, class_name::CreateObject)
class CObject
{
public:
CObject(){}
~CObject(){}
virtual CRuntimeClass * GetRuntimeClass() const;
BOOL IsKindOf(const CRuntimeClass* pClass) const;
public:
static CRuntimeClass classCObject;
virtual void SayHello()
{
std::cout<<"Hello CObject\n";
}
};
class CCmdTarget : public CObject
{
DECLEAR_DYNAMIC(CCmdTarget)
public:
CCmdTarget(){}
~CCmdTarget(){}
};
class CWinThread : public CCmdTarget
{
DECLEAR_DYNAMIC(CWinThread)
public:
CWinThread(){}
~CWinThread(){}
virtual BOOL InitInstance()
{
return TRUE;
}
virtual int Run()
{
return 1;
}
};
class CWnd;
class CWinApp : public CWinThread
{
DECLEAR_DYNAMIC(CWinApp)
public:
CWinApp* m_pCurrentWinApp;
CWnd* m_pMainWnd;
public:
CWinApp(){}
~CWinApp(){}
virtual BOOL InitApplication()
{
return TRUE;
}
virtual BOOL InitInstance()
{
return TRUE;
}
virtual int Run()
{
return CWinThread::Run();
}
};
class CDocument : public CCmdTarget
{
DECLEAR_DYNAMIC(CDocument)
public:
CDocument(){}
~CDocument(){}
};
class CWnd : public CCmdTarget
{
DECLARE_DYNCREATE(CWnd)
public:
CWnd(){std::cout<<"CWnd Constructor \n";}
~CWnd(){}
virtual BOOL Create();
BOOL CreateEx();
virtual BOOL PreCreateWindow();
void SayHello()
{
std::cout<<"Hello CWnd\n";
}
};
class CFrameWnd : public CWnd
{
DECLARE_DYNCREATE(CFrameWnd)
public:
CFrameWnd()
{
std::cout<<"CFrameWnd Constrcutor\n";
}
~CFrameWnd(){}
BOOL Create();
virtual BOOL PreCreateWindow();
void SayHello()
{
std::cout<<"Hello CFrameWnd\n";
}
};
class CView : public CWnd
{
DECLEAR_DYNAMIC(CView)
public:
CView(){}
~CView(){}
};
CWinApp *AfxGetApp();
//MFC.cpp
#include "MY.h"
extern CMyWinApp theApp;
static char szCObject[] = "CObject";
struct CRuntimeClass CObject::classCObject = { szCObject, sizeof(CObject), 0xffff, NULL, NULL, NULL};
static AFX_CLASSINIT _init_CObject(&CObject::classCObject);
CRuntimeClass* CRuntimeClass::m_pFirstClass = NULL;
AFX_CLASSINIT::AFX_CLASSINIT(CRuntimeClass* pNewClass)
{
pNewClass->m_pNextClass = CRuntimeClass::m_pFirstClass;
CRuntimeClass::m_pFirstClass = pNewClass;
}
CObject * CRuntimeClass::CreateObject()
{
if (m_pfnCreateObject == NULL)
{
TRACE1("Error: trying to create object which is not declare");
return NULL;
}
CObject *pCObject = NULL;
pCObject = (*m_pfnCreateObject)();
return pCObject;
}
CRuntimeClass* PASCAL CRuntimeClass::Load()
{
char szClassName[64];
CRuntimeClass *pClass;
std::cout<<"enter a class name:";
std::cin>>szClassName;
for (pClass = m_pFirstClass; pClass != NULL; pClass = pClass->m_pNextClass)
{
if (strcmp(szClassName, pClass->m_lpszClassName) == 0)
{
return pClass;
}
}
TRACE1("Error: Class not found\n");
return NULL;
}
CRuntimeClass* CObject::GetRuntimeClass()const
{
return &CObject::classCObject;
}
BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const
{
CRuntimeClass * pClassThis = GetRuntimeClass();
while(pClassThis != NULL)
{
if (pClassThis == pClass)
{
return TRUE;
}
pClassThis = pClassThis->m_pBaseClass;
}
return FALSE;
}
BOOL CWnd::Create()
{
return TRUE;
}
BOOL CWnd::CreateEx()
{
PreCreateWindow();
return TRUE;
}
BOOL CWnd::PreCreateWindow()
{
return TRUE;
}
BOOL CFrameWnd::Create()
{
CreateEx();
return TRUE;
}
BOOL CFrameWnd::PreCreateWindow()
{
return TRUE;
}
CWinApp *AfxGetApp()
{
return theApp.m_pCurrentWinApp;
}
IMPLEMENT_DYNAMIC(CCmdTarget, CObject)
IMPLEMENT_DYNAMIC(CWinThread, CCmdTarget)
IMPLEMENT_DYNAMIC(CWinApp, CWinThread)
IMPLEMENT_DYNAMIC(CDocument, CCmdTarget)
IMPLEMENT_DYNCREATE(CWnd, CCmdTarget)
IMPLEMENT_DYNAMIC(CView, CWnd)
IMPLEMENT_DYNCREATE(CFrameWnd, CWnd)
//MY.h
#include "MFC.h"
class CMyWinApp : public CWinApp
{
public:
CMyWinApp(){}
~CMyWinApp(){}
virtual BOOL InitInstance();
};
class CMyFrameWnd : public CFrameWnd
{
DECLARE_DYNCREATE(CMyFrameWnd)
public:
CMyFrameWnd();
~CMyFrameWnd(){}
void SayHello()
{
std::cout<<"Hello CMyFrameWnd\n";
}
};
class CMyDoc : public CDocument
{
DECLARE_DYNCREATE(CMyDoc)
public:
CMyDoc(){}
~CMyDoc(){}
void SayHello()
{
std::cout<<"Hello CMyDoc\n";
}
};
class CMyView : public CView
{
DECLARE_DYNCREATE(CMyView)
public:
CMyView()
{
std::cout<<"CMyView Constructor\n";
}
~CMyView(){}
void SayHello()
{
std::cout<<"Hello CMyView\n";
}
};
void AfxPrintAllClasses();
//MY.cpp
#include "MY.h"
CMyWinApp theApp;
BOOL CMyWinApp::InitInstance()
{
m_pMainWnd = new CMyFrameWnd;
return TRUE;
}
CMyFrameWnd::CMyFrameWnd()
{
std::cout<<"CMyFrameWnd Constructor\n";
Create();
}
IMPLEMENT_DYNCREATE(CMyFrameWnd, CFrameWnd)
IMPLEMENT_DYNCREATE(CMyDoc, CDocument)
IMPLEMENT_DYNCREATE(CMyView, CView)
//main.cpp
#include "MY.h"
int main(int argc, char argv[])
{
CWinApp *pApp = AfxGetApp();
pApp->InitApplication();
pApp->InitInstance();
pApp->Run();
return 0;
}