您的位置:首页 > 其它

MFC框架之我见——模拟分析

2008-08-28 10:40 176 查看
MFC框架之我见——模拟分析

复习MFC知识,再次翻看侯捷的《深入浅出》,下面是模拟MFC框架运行的代码
//
// mfc.h
//
//
// Written by Leezhm 27st August, 2008
// Contact : Leezhm@126.com
//

//------------CObject Class
//            |
//            |---CCmdTarget Class
//                |
//                |---CWinThread Class
//                |   |
//                |   |---CWinApp Class
//                |       |
//                |       |---CMyApp Class
//                |
//                |---CWnd
//                |   |
//                |   |---CView Class
//                |   |   |
//                |   |   |---CMyView Class
//                |   |
//                |   |---CFrameWnd Class
//                |       |
//                |       |---CMyFrameWnd Class
//                |
//                |---CDocument Class
//                    |
//                    |---CMyDoc Class
#ifndef __H_MFC__
#define __H_MFC__
class CObject
{
public:
CObject();
~CObject();
};
class CCmdTarget : public CObject
{
public:
CCmdTarget();
~CCmdTarget();
};
class CWinThread : public CCmdTarget
{
public:
CWinThread();
~CWinThread();
public:
virtual bool InitInstance();
virtual bool Run();
};
class CWnd;
class CWinApp : public CWinThread
{
public:
CWinApp();
~CWinApp();
public:
virtual bool InitApplication();
virtual bool InitInstance();
virtual bool Run();
public:
CWinApp * m_pCurrentWinApp;
CWnd    * m_pMainWnd;
};
class CWnd : public CCmdTarget
{
public:
CWnd();
~CWnd();
public:
virtual bool Create();
bool CreateEx();
virtual bool PreCreateWindow();
};
class CView : public CWnd
{
public:
CView();
~CView();
};
class CFrameWnd : public CWnd
{
public:
CFrameWnd();
~CFrameWnd();
public:
bool Create();
virtual bool PreCreateWindow();
};
class CDocument : public CCmdTarget
{
public:
CDocument();
~CDocument();
};
#endif //__H_MFC__
//
// mfc.cpp
//
#include "mfc.h"
#include <iostream>
using std::cout;
using std::endl;
CObject::CObject()
{
cout<<"CObject Constructor"<<endl;
}
CObject::~CObject()
{
cout<<"CObject Destructor"<<endl;
}
CCmdTarget::CCmdTarget()
{
cout<<"CCmdTarget Constructor"<<endl;
}
CCmdTarget::~CCmdTarget()
{
cout<<"CCmdTarget Destructor"<<endl;
}
CWinThread::CWinThread()
{
cout<<"CWinThread Constructor"<<endl;
}
CWinThread::~CWinThread()
{
cout<<"CWinThread Destructor"<<endl;
}
bool CWinThread::InitInstance()
{
cout<<"CWinThread::InitInstance"<<endl;
return true;
}
bool CWinThread::Run()
{
cout<<"CWinThread::Run"<<endl;
return true;
}
CWinApp::CWinApp()
{
m_pCurrentWinApp = this;
cout<<"CWinApp Constructor"<<endl;
}
CWinApp::~CWinApp()
{
cout<<"CWinApp Destructor"<<endl;
}
bool CWinApp::InitApplication()
{
cout<<"CWinApp::InitApplication"<<endl;
return true;
}
bool CWinApp::InitInstance()
{
cout<<"CWinApp::InitInstance"<<endl;
return true;
}
bool CWinApp::Run()
{
cout<<"CWinApp::Run"<<endl;
return CWinThread::Run();
}
CWnd::CWnd()
{
cout<<"CWnd Constructor"<<endl;
}
CWnd::~CWnd()
{
cout<<"CWnd Destructor"<<endl;
}
bool CWnd::Create()
{
cout<<"CWnd::Create"<<endl;
return true;
}
bool CWnd::CreateEx()
{
cout<<"CWnd::CreateEx"<<endl;

PreCreateWindow();
return true;
}
bool CWnd::PreCreateWindow()
{
cout<<"CWnd::PreCreateWindow"<<endl;
return true;
}
CView::CView()
{
cout<<"CView Constructor"<<endl;
}
CView::~CView()
{
cout<<"CView Destructor"<<endl;
}
CFrameWnd::CFrameWnd()
{
cout<<"CFrameWnd Constructor"<<endl;
}
CFrameWnd::~CFrameWnd()
{
cout<<"CFrameWnd Destructor"<<endl;
}
bool CFrameWnd::Create()
{
cout<<"CFrameWnd::Create"<<endl;
CreateEx();
return true;
}
bool CFrameWnd::PreCreateWindow()
{
cout<<"CFrameWnd::PreCreateWindow"<<endl;
return true;
}
CDocument::CDocument()
{
cout<<"CDocument Constructor"<<endl;
}
CDocument::~CDocument()
{
cout<<"CDocument Destructor"<<endl;
}
//
// myMFC.h
//
#ifndef __H_MYMFC__
#define __H_MYMFC__
#include "mfc.h"
// global function
CWinApp * myGetWinApp();
class CMyApp : public CWinApp
{
public:
CMyApp();
~CMyApp();
virtual bool InitInstance();
};
class CMyFrameWnd : public CFrameWnd
{
public:
CMyFrameWnd();
~CMyFrameWnd();
};
#endif //__H_MYMFC__
//
// myMFC.cpp
//
#include "myMFC.h"
#include <iostream>
using std::cout;
using std::endl;
// global variable
CMyApp  theApp;
CWinApp * myGetWinApp()
{
if(!theApp.m_pCurrentWinApp)
return NULL;
return theApp.m_pCurrentWinApp;
}
CMyApp::CMyApp()
{
cout<<"CMyApp Constructor"<<endl;
}
CMyApp::~CMyApp()
{
cout<<"CMyApp Destructor"<<endl;
}
bool CMyApp::InitInstance()
{
cout<<"CMyApp::InitInstance"<<endl;
m_pMainWnd = new CMyFrameWnd();
return true;
}
CMyFrameWnd::CMyFrameWnd()
{
cout<<"CMyFrameWnd Constructor"<<endl;
Create();
}
CMyFrameWnd::~CMyFrameWnd()
{
cout<<"CMyFrameWnd Destructor"<<endl;
}
void main()
{
cout<<endl;
CWinApp * pApp = myGetWinApp();
pApp->InitApplication();
pApp->InitInstance();
pApp->Run();
cout<<endl;
}


OK,代码贴完了,再看看运行的结果是么样的。



在这张图片中我们应该注意全局CMyApp对象的创建、销毁时的构造函数和析构函数的调用规范,以及各个函数的调用次序,要理解这些,需要理解class的继承、多态原理。



在这张图片中我们可以更实在地看到各个class的继承关系,还需要注意的是在子类中的虚拟函数表中各个函数的地址,是不是符合class的多态。

好了,运行的结果以及调试结果都在上面。根据上面的来分析下:

首先,关于全局变量theApp的创建过程中子类和父类的构造函数调用是符合C++语法的,先是最顶级父类构造函数,而后依次到最终的子类的构造函数;析构函数是刚好相反的。

然后进入了main函数,首先会得到this指针,也即时全局变量theApp。

pApp->InitApplication(...)调用,由于在CMyApp类中并没有对基类CWinApp中的虚拟函数进行重写(Override,也有叫覆盖,注意与类成员的重载区分开来),根据继承和多态原理,应该是调用的是CWinApp::InitApplication(...)函数

pApp->InitInstance(...)调用,由于在CMyApp中继承并Override了基类的虚拟函数InitInstance函数,所以调用的是CMyApp::InitInstance(...)函数。注意在这个函数中语句:m_pMainWnd = new CMyFrameWnd();创建了CMyFrameWnd对象,这必然要引发一序列基类的构造的调用。

还要注意的是在CMyFrameWnd的构造函数中调用了Create这个成员函数,Create函数又调用了CreateEx这个从基类继承的函数,而CreateEx函数中调用了PreCreateWindow函数。这个时候我们仔细看看源码,知道CFrameWnd从基类CWnd继承并重写了PreCreatWindow这个函数,所以这个时候调用的是CFrameWnd::PreCreateWindow(...)函数。理解这个数是一个关键点。

最后Run函数的调用还是继承和多态原理,注意一下CWinApp::Run(...)的实现

bool CWinApp::Run()
{
cout<<"CWinApp::Run"<<endl;
return CWinThread::Run();
}


它返回的是CWinThread::Run(...),这就是这个地方不符合继承重写原理的原因。

好了,整个分析完了,在下篇中将结合MFC的源码来分析整个模拟过程。



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: