在前几天学习自己动手创建了一个mfc程序之后,生出了一个疑问,作为一个新手,在学习c++标准语法的时候,基本都是控制台程序,而且众所周知程序都会有一个入口点也就是main函数,而在mfc程序中,只是定义了一个全局对象theApp,和重写了一个初始化函数,没有看到任何的主函数,然后资料上说mfc将入口函数也给封装起来了,因此今天准备跟踪一下mfc程序的执行流程,以FirstMFC为例
因为全局变量先于入口函数执行,因此程序会先执行CMyWinApp myApp; 因为该过程会创建对象,进入构造函数,因此在他之前加断点调试
按F11进入构造函数内部,会先进入本类的构造函数,再按F11进入父类的构造函数
在父类的构造函数中发现有两个宏定义AFX_MODULE_STATE和AFX_MODULE_THREAD_STATE,一头雾水,在网上查阅了很多资料也没得出个所以然,在这里分享一篇分析较好的文章
http://blog.163.com/maple_zh@126/blog/static/10712959820132219189932/
继续跟代码发现这两个宏其实是两个类,都派生自一个叫CNoTrackObject的类,进入这个类,发现它冲在了new跟delete操作符
至于这个类出现的意义,在网上查询得到的解释是用来记录内存块和给每一个对象分配一个单独的内存块(有待考证),最终得到信息是
AFX_MODULE_STATE 定义的变量记录当前程序模块状态信息
AFX_MODULE_THREAD_STATE 定义的变量记录当前程序线程状态信息
而用pModuleState指针和pThreadState指针分别获取了_afxThreadState和m_thread这两个全局变量的地址
执行到断点处可以发现,mfc将当前myApp对象的地址保存到了AFX_MODULE_THREAD_STATE类的成员变量CWinThread* m_pCurrentWinApp中,即CWinApp(CMyWinApp的父类)拿到了CMyWinApp的地址,而下面的AfxGetThread又重新拿到了myApp的地址(不理解)
CWinThread* AFXAPI AfxGetThread()
{
// check for current thread in module thread state
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
CWinThread* pThread = pState->m_pCurrentWinThread;
return pThread;
}
继续执行mfc又将将当前myApp对象的地址保存到了AFX_MODULE_STATE类的成员变量CWinApp* m_pCurrentWinApp中
从这里可以看出CwinApp的构造函数主要完成了以下几个功能
1) 将myApp对象地址保存到当前程序模块状态信息中。
2) 将myApp对象地址保存到当前程序线程状态信息中。
3) AfxGetThread/AfxGetApp – 返回myApp对象地址。
因此可以猜测,当前myApp对象地址会在之后的窗口创建过程中会用到
进入入口函数
点击单步调试进入AfxWinMain
CWinThread* pThread = AfxGetThread();//获取myApp对象地址
CWinApp* pApp = AfxGetApp();//获取myApp对象地址
// AFX internal initialization
if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))//初始化mfc库
goto InitFailure;
// App global initializations (rare)
if (pApp != NULL && !pApp->InitApplication())//初始化应用程序
goto InitFailure;
// Perform specific initializations
if (!pThread->InitInstance())
{
if (pThread->m_pMainWnd != NULL)
{
TRACE(traceAppMsg, 0, "Warning: Destroying non-NULL m_pMainWnd\n");
pThread->m_pMainWnd->DestroyWindow();
}
nReturnCode = pThread->ExitInstance();
goto InitFailure;
}
nReturnCode = pThread->Run();
由代码可以看出在经过一系列初始化之后,执行到pThread->InitInstance,而pThread为基类指针存的是子类myApp的地址,由多态可以得到程序会调用我们重写的 CMyWinApp::InitInstance函数
此时程序回到我们写的初始化函数开始创建窗口