标签:
在文章开始是我们的观点就强调过了,要想用好一个工具,就必须深入了解这个工具的工作原理。而仿真,正是最好的方法。
如何仿真呢?我们在console程序中仿真MFC,这样可以把程序结构的负荷降到最低。作者在仿真中的原则是:简化再简化,简化到不能再简化。请注意,以下所有程序的类层次结构、类名称、变量名称、结构名称、函数名称、函数内容,都以MFC为仿真对象,具体而微。
在档案的安排上,作者把仿真MFC的类集中在MFC.H和MFC.CPP中,把自己派生的类集中在MY.H和MY.CPP中。对于自定义的类,我的命名方式是在父类的名称前面加一个“My”,例如派生自CWinApp者,名为CMyWinApp,派生自CDocument者,名为CMyDoc。
特别说明:我一直认为,扎实的基础是以后进阶高度快速提升的不二法门,所以希望大家能够跟着我沉住气,一点一点挖出MFC整个的运行机制,相信这会对大家和对我自己更有裨益。从这一章开始,我会分析的很细,可能每一节讲的很少,但务必求精不贪多,希望大家可以理解。
首先以一个极简单的程序Frame1,把MFC数个最重要的类的层次关系仿真出来:
这个例程仿真MFC的类层次。后续会在这个类层次上开发新的能力。在这些名为Frame?的范例中,我以MFC程序代码为蓝本,尽量仿真MFC的内部行为,并且使用完全相同的类名称、函数名称、变量名称。这会对我们在后面深入探讨MFC时有莫大的助益。
Frame 1 范例程序
首先是MFC.H头文件:
#include <iostream>
using namespace std;
class CObject //基类CObject
{
public:
CObject::CObject() { cout << "CObject Constructor \n"; }
CObject::~CObject() {cout << "CObject Destructor \n"; };
};
class CCmdTarget : public CObject
{
public:
CCmdTarget::CCmdTarget() { cout << "CCmdTarget Constructor \n"; }
CCmdTarget::~CCmdTarget() {cout << "CCmdTarget Destructor \n"; };
};
class CWinThread : public CCmdTarget
{
public:
CWinThread::CWinThread() { cout << "CWinThread Constructor \n"; }
CWinThread::~CWinThread() {cout << "CWinThread Destructor \n"; };
};
class CWinApp : public CWinThread
{
public:
CWinApp* m_pCurrentWinApp;
public:
CWinApp::CWinApp() { m_pCurrentWinApp = this;
cout << "CWinApp Constructor \n"; } //这个类的对象在创建时就会调用构造函数,所以也就把当前类对象指针保存到了m_pCurrentWinAPP
CWinApp::~CWinApp() { cout << "CWinApp Destructor \n"; }
};
class CWnd : public CCmdTarget
{
public:
CWnd::CWnd() { cout << "CWnd Constructor \n"; }
CWnd::~CWnd() { cout << "CWnd Destructor \n"; }
};
class CFrameWnd : public CWnd
{
public:
CFrameWnd::CFrameWnd() { cout << "CFrameWnd Constructor \n"; }
CFrameWnd::~CFrameWnd() { cout << "CFrameWnd Destructor \n"; }
};
class CView : public CWnd
{
public:
CView::CView() { cout << "CView Constructor \n"; }
CView::~CView() { cout << "CView Destructor \n"; }
};
//全局函数
CWinApp* AfxGetApp();
然后是MFC.CPP:
#include "MFC.h"
#include "MY.h"
extern CMyWinApp theApp;
CWinApp* AfxGetApp()
{
return theApp.m_pCurrentWinApp;
}
接下来是从MFC类中派生出来的我们自己的App类:
MY.H头文件:
#include <iostream>
#include "MFC.h"
class CMyWinApp : public CWinApp
{
public:
CMyWinApp::CMyWinApp() { cout << "CMyWinApp Constructor \n"; }
CMyWinApp::~CMyWinApp() { cout << "CMyWinApp Destructor \n"; }
};
class CMyFrameWnd : public CFrameWnd
{
public:
CMyFrameWnd() { cout << "CMyFrameWnd Constructor \n"; }
~CMyFrameWnd() { cout << "CMyFrameWnd Destructor \n"; }
};
MY.CPP源文件:
#include "MY.h"
CMyWinApp theApp;
void main()
{
CWinApp* pApp = AfxGetApp();
}
执行的结果:
CObject Constructor
CCmdTarget Constructor
CWinThread Constructor
CWinApp Constructor
CMyWinApp Constructor
从程序中可以看到,Frame1并没有new任何对象,反倒是有一个全局对象theApp存在。C++规定,全局对象的建构将比程序进入点(在DOS环境为main,在Windows环境为WinMain)更早。所以theApp的构造函数将更早于main。换句话说,你所看到的执行结果中的那些构造函数输出操作全都是在main函数之前完成的。CMyWinApp Destructor
CWinApp Destructor
CWinThread Destructor
CCmdTarget Destructor
CObject Destructor
在解释一下,因为定义theApp这个全局变量的类为CMyWinApp,而这个类是从一系列基类继承下来的,也就意味着你在声明这个全局变量的时候,就已经依次调用了各个类的构造函数和析构函数,所以才会有上面的输出结果。
main函数调用全局函数AfxGetApp以取得theApp的对象指针。这完全是仿真MFC程序的手法。
//MY.CPPCMyWinApp theApp;void main(){CWinApp* pApp = AfxGetApp();pApp->InitApplication();pApp->InitInstance();pApp->Run();}其中,pApp指向theApp全局对象。这里我们开始看到了虚拟函数的妙用:pApp->InitApplication()调用的是CWinApp::InitApplication,pApp->InitInstance() 调用的是CMyWinApp::InitInstance( 因为CMyWinApp改写了它),pApp->Run()调用的是CWinApp::Run,好,请注意一下CMyWinApp::InitInstance的操作,以及它所引发的行为:BOOL CMyWinApp::InitInstance(){cout << "CMyWinApp::InitInstance \n";m_pMainWnd = new CMyFrameWnd; //还记得吗?动态创建时引发CMyFrameWnd::CMyFrameWnd构造函数return TRUE;}CMyFrameWnd::CMyFrameWnd(){Create(); //Create是虚拟函数,但是CMyFrameWnd未改写它,所以引发父类的CFrameWnd::Create}BOOL CFrameWnd::Create(){cout << " CFrameWnd::Create \n";CreateEx(); //CreateEx是虚拟函数,但CFrameWnd未改写之,所以引发CWnd::CreateExreturn TRUE;}BOOL CWnd :: CreateEx(){cout << " CWnd:: CreateEx \n";PreCreateWindow(); //这是一个虚拟函数,CWnd中有定义,CFrameWnd也改写了它。那么你说这里到底是调用CWnd::PreCreateWindow还是CFrameWnd::PreCreateWindow呢?return TRUE;}BOOL CFrameWnd :: PreCreateWindow(){cout<<"CFrameWnd::PreCreateWindow \n";return TRUE;}其实,这里调用的是CFrameWnd::PreCreateWindow。这便是第2章的“Object slicing与虚拟函数”一节所说的“虚拟函数的一个极重要的行为方式”。
当然,在这里这些函数什么动作也没做,只是输出一个标识字符串,我们现在主要的目的是让你先熟悉MFC程序的流程。
执行结果:
CWinApp::InitApplication
CMyWinApp::InitInstance
CMyFrameWnd::CMyFrameWnd
CFrameWnd::Create
CWnd::CreateEx
CFrameWnd::PreCreateWindow
CWinApp::Run
CWinThread::Run
Frame2范例程序
MFC.H头文件
#define BOOL int
#define TRUE 1
#define FALSE 0
#include <iostream>
using namespace std;
class CObject //基类CObject
{
public:
CObject::CObject() { }
CObject::~CObject() { }
};
class CCmdTarget : public CObject
{
public:
CCmdTarget::CCmdTarget() { }
CCmdTarget::~CCmdTarget() { }
};
class CWinThread : public CCmdTarget
{
public:
CWinThread::CWinThread() { }
CWinThread::~CWinThread() { }
virtual BOOL InitInstance()
{
cout <<"CWinThread :: InitInstance \n";
return TRUE;
}
virtual BOOL Run()
{
cout <<"CWinThread :: Run \n";
return TRUE;
}
};
class CWinApp : public CWinThread
{
public:
CWinApp* m_pCurrentWinApp;
CWnd* m_pMainWnd;
public:
CWinApp::CWinApp() { m_pCurrentWinApp = this;}
CWinApp::~CWinApp() { }
virtual BOOL InitApplication()
{
cout <<"CWinApp :: InitApplication \n";
return TRUE;
}
virtual BOOL InitInstance()
{
cout <<"CWinApp :: InitInstance \n";
return TRUE;
}
virtual BOOL Run()
{
cout <<"CWinApp :: Run \n";
return CWinThread::Run();
}
};
class CWnd : public CCmdTarget
{
public:
CWnd::CWnd() { }
CWnd::~CWnd() { }
virtual BOOL Create();
BOOL CreateEx();
virtual BOOL PreCreateWindow();
};
class CFrameWnd : public CWnd
{
public:
CFrameWnd::CFrameWnd() { }
CFrameWnd::~CFrameWnd() { }
BOOL Create();
virtual BOOL PreCreateWindow();
};
class CView : public CWnd
{
public:
CView::CView() { }
CView::~CView() { }
};
//全局函数
CWinApp* AfxGetApp();
MFC.CPP源文件:
#include "MFC.h"
#include "MY.h"
extern CMyWinApp theApp;
CWinApp* AfxGetApp()
{
return theApp.m_pCurrentWinApp;
}
BOOL CWnd::Create()
{
cout << "CWnd ::Create \n";
return TRUE;
}
BOOL CWnd::CreateEx()
{
cout<<"CWnd::CreateEx \n";
PreCreateWindow();
return TRUE;
}
BOOL CWnd::PreCreateWindow()
{
cout << "CWnd ::PreCreateWindow \n";
return TRUE;
}
BOOL CFrameWnd::Create()
{
cout<<"CFrameWnd::Create \n";
CreateEx();
return TRUE;
}
BOOL CFrameWnd::PreCreateWindow()
{
cout<<"CFrameWnd::PreCreateWindow \n";
return TRUE;
}
MY.H头文件
#include <iostream>
#include "MFC.h"
class CMyWinApp : public CWinApp
{
public:
CMyWinApp::CMyWinApp() { }
CMyWinApp::~CMyWinApp() { }
virtual BOOL InitInstance();
};
class CMyFrameWnd : public CFrameWnd
{
public:
CMyFrameWnd();
~CMyFrameWnd() { cout << "CMyFrameWnd Destructor \n"; }
};
MY.CPP源文件:
#include "MY.h"
CMyWinApp theApp;
BOOL CMyWinApp::InitInstance()
{
cout<<"CMyWinApp::InitInstance \n";
m_pMainWnd = new CMyFrameWnd;
return TRUE;
}
CMyFrameWnd::CMyFrameWnd()
{
cout<<"CMyFrameWnd::CMyFrameWnd \n";
Create();
}
void main()
{
CWinApp* pApp = AfxGetApp();
pApp->InitApplication();
pApp->InitInstance();
pApp->Run();
}
程序过程有些繁琐,所以我绘制了一下流程图,从总体上来看整个过程,应该更有注意理解:
下面是在InitInstance()中创建窗口的过程:
标签:
原文地址:http://blog.csdn.net/walkman_lfq/article/details/51328878