1.六大关键技术:
①:MFC程序的初始化过程
②:RTTI(Runtime Type Information) 运行时类型识别
③:Dynamic Creation 动态创建
④:Persistence 永久保存
⑤:Message Mapping 消息映射
⑥:Message Routing 消息传递
2.MFC数个之最重要的类的层次关系:
CMyWinApp theApp;
void main(){
CWinApp* pApp = AfxGetApp();
pApp->InitApplication();
pApp->InitInstance();
pAPP->Run();
}
构造、析构次序:
CObject 构造->CCmdTarget构造->CWinThread构造->CWinApp构造->CMyWinApp构造
CMyWinApp析构->CWinApp析构->CWinThread析构->CCmdTarget析构造->CObject 析构
main执行顺序:
CWinApp::InitApplication->CMyWinApp::InitInstance->CMyFrameWnd::CMyFrameWnd->CFrameWnd::Create->CWnd::CreateEx->CFrameWnd::PreCreateWindow->CWinApp::Run->CWinThread::Run
3.RTTI(运行时识别)
要达到RTTI的能力,我们(类库的设计者)一定要在类建构起来的时候,记录必要的信息,以建立型录。型录中的类信息,最好以链表方式连接起来,将来方便一一比较。
我们这份“类型型录”的链表元素将以CRuntimeClass描述之。
struct CRuntimeClass
{
LPCSTR m_lpszClassName;
int m_nObjectSize;
UINT m_wSchema;
CObect* (PASCAL* m_pfnCreateObject)();
CRuntimeClass* m_pBaseClass; //基类
static CRuntimeClass * pFirstClass;
CRuntimeClass* m_pNextClass; //下一个注册类
};
我们希望,每一个类都能拥有这样一个CRuntimeClass成员变量,并且最好有一定的命名规则(例如在类名称之前冠以“class”作为它的名称),然后,经由某种手段将整个类库建构好之后,“类别型录”能呈现类似这样的风貌:
为了神不知鬼不觉把CRuntimeClass对象塞到类之中,并声明一个可用抓到该对象地址的函数,我们定义DECLARE_DYNAMIC宏如下:
#define DECLARE_DYNAMIC(class_name) \
public: \
static CRuntimeClass class##class_name; \
virtual CRuntimeClass* GetRuntimeClass() const;
##用来告诉编译器,把两个字符串系在一起。
各个CRuntimeClass对象的内容指定以及连接工作最好也能神不知鬼不觉,于是定义IMPLEMENT_DYNAMIC宏:
#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) \
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 RUNTIME_CLASS(class_name) \
(&class_name::class##class_name)
其中struct AFX_CLASSINIT,定义如下:
struct AFX_CLASSINIT
{AFX_CLASSINIT(CRuntimeClass* pNewClass); };
这表示它有一个构造函数(C++的struct和class都有构造函数),定义如下:
CLASSINIT::CLASSINIT(CRuntimeClass* pNewClass)
{
pNewClass->m_pNextClass = CRuntimeClass::pFirstClass;
CRuntimeClass::pFirstClass = pNewClass;
}
此次构造负责linked list的连接工作
现在来看看这个例程:
class CView : public CWnd
{
DELARE_DYNAMIC(CView)
…
};
IMPLEMENT_DYNAMIC(CView, CWnd)
于是,程序中只需要简简单单的两个宏DELARE_DYNAMIC(Cxxx)和IMPLEMENT_DYNAMIC(Cxxx,Cxxxbase),就完成了构建数据并加入链表的工作:
但是链表的头要特别处理:
class CObject
{
public:
virtual CRuntimeClass* GetRuntimeClass() const;
…
public:
static CRuntimeClass classCObject;
};
static char szCObject[] = “CObject”;
struct CRuntimeClass CObject::classCObject = {
szCObject, sizeof(CObject), 0xffff, NULL, NULL, NULL};
static AFX_CLASSINIT _initCObject(&CObject::classCObject);
CRuntimeClass* class_name::GetRuntimeClass() const
{return &CObject::classCObject;}
CRuntimeClass* CRuntimeClass::pFirstClass = NULL;
整个“类别型录”链表的头部就形成了:
于是我们可以织出这样一张大网:
有了这张“类别型录”网,要实现IsKindOf功能,再轻松不过了:
1.为CObject加上一个IsKindOf函数,于是此函数将被所有类继承,它将把参数所指定的某个CRuntimeClass对象拿来与类别型录中的元素一一比较,比较成功,就传回TRUE,否则传回FALSE。
class CObject
{
public:
…
BOOL IsKindOf(const CRuntimeClass* pClass) const;
};
BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const
{
CRuntimeClass* pClassThis = GetRuntimeClass();
while(pClassThis != NULL)
{
if(pClassThis == pClass) return TRUE;
pClassThis = pClassThis->m_pBaseClass;
}
return FALSE;
}
4.Dynamic Creation(动态创建)
我们可以把类的大小记录在类别型录中,把建构函数(不是构造函数)也记录在类别型录中,当程序在执行期获得一个类名称,它就可以在“类别型录网”中找出对应的元素,然后调用其建构函数,产生出对象。
于是CRuntimeClass变为:
struct CRuntimeClass
{
LPCSTR m_lpszClassName;
int m_nObjectSize;
UINT m_wSchema; //schema number of the loaded class
CObect* (PASCAL* m_pfnCreateObject)();
CRuntimeClass* m_pBaseClass; //基类
CObject* CreateObject();
static CRuntimeClass* PASCAL Load();
static CRuntimeClass * pFirstClass;
CRuntimeClass* m_pNextClass; //下一个注册类
};
为了适应CRuntimeClass中新增的成员变量,我们再添两个宏,DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE:
#define DECLARE_DYNCREATE(class_name) \
DECLARE_DYNAMIC(class_name) \
static CObject* PASCAL CreateObject();
#define IMPLEMENT_DYNCREATE(class_name, base_class_name) \
CObject* PASCAL class_name::CreateObject() \
{return new class_name;} \
_IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFF, \
class_name::CreateObject)
以CFrameWnd为例:
class CFrameWnd : public CWnd
{
DECLARE_DYNCREATE(CFrameWnd)
…
};
IMPLEMENT_DYNCREATE(CFrameWnd, Cwnd)
图示:
拥有动态创建能力的类库,必然拥有运行时类型识别能力。
现在开始仿真动态创建,首先在main函数中加上这段代码:
void main()
{
CRuntimeClass* pClassRef;
CObject* pOb;
while(1)
{
if((pClassRef = CRuntimeClass::Load()) == NULL) break;
pOb = pClassRef->CreateObject();
if(pOb != NULL)
pOb->SayHello();
}
}
并设计CRuntimeClass::CreateObject和CRuntimeClass::Load如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | CObject *CRuntimeClass::CreateObject() { If(m_pfnCreateObject==NULL)//不支持动态创建。 { throw runtime_error("此类不支持动态创建"); Return NULL; } CObject*pObject=(*m_pfnCreateObject)(); Return pObject; } CRuntimeClass*PASCL CRuntimeClass::Load() { Char szClassName[64]; CRuntimeClass*pClass cout<<"输入一个类名:"; cin>>szClassName; for(pClass=pFirstClass;pClass;pClass=pClass->m_pNextClass) { if(strcmp(szClassName,pClass->m_lpszClassName)==0) return pClass; return NULL; } } |
转载请标注来源:http://www.alonemonkey.com
By:AloneMonkey