MFC的Main函数跑哪去了
 
我們會發現C++中可以有一個單獨的main函數,不用包含在哪個類中,另外還有不屬于任何類的全局變量或全局函數這自然就不是純粹的面向對象語言了.所以說C++支持多種編程范式嘛,可以是跟C完全一樣的面向過程范式,或者再加些普通的類就是基于對象的范式了,如果再用到繼承和多態就是面向對象了,而要是用到模板就是泛型范式了.而且這些范式可以互相混合用.而C#就是純的面向對象,所以它里面雖然也有main函數,但也是要放在一個類里面去,至于具體放哪個類無所謂,你隨便放.一般默認是放Program這個類里.當然并不是說純的面向對象就比混合的范式好,應該各有優缺點.
哎扯得有點遠了,言歸正傳.
?
SDK中的流程
開發一個帶界面的SDK程序大致流程是這樣的.首先自然是要有個main函數做入口點.然后按下面的步驟來(為了討論方便,只說大概流程,代碼也是不完整的)
int _tWinain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
?? MSG msg;
?? InitApplicatio(HINSTANCE hInstance)? ?//第1步,注冊窗體類,并在這里指定了窗體過程WndProc
???InitInstance(HINSTANCE hInstance, int nCmdShow)? ?//第2步,創建窗體
while (GetMessage(&msg, NULL, 0, 0))??? //第3步消息循環,分派消息
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;? //第4步,退出程序
}
BOOL InitApplicatio(HINSTANCE hInstance)
{
??return RegisterClass(...);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
CreateWindow(...); //創建窗體
ShowWindow(...); //顯示窗體
UpdateWindow(...); //送出WM_PAINT
return TRUE;
}
LRESULT CALLBACK WndProc(...){ }
?
在MFC中生成一個有界面的程序大體過程也一樣,只不過封裝起來了.那我們感興趣的就是兩個問題.
1.MFC中有沒有main函數了,如果有它跑哪去了??
2.如果有main函數,它里面的那4步涉及到的具體操作是否也跟win32 API一樣?
下面我們就來一一解答下
?
MFC封裝背后流程
?
實際上候捷那本深入淺出MFC里面有講的很清楚了.不過由于講的太詳細了,有幾十頁,看的容易暈,而且他舉的例都是老版本的MFC類,在新版本中一些類的函數會有一點點變化.
我這里就只概括的講下最簡潔的流程.先假如有類CMyApp繼承自CWinApp吧
?
1.針對第一個問題,MFC里是有用到main函數的
// export WinMain to force linkage to this module
extern int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine, int nCmdShow);
就是這一個函數,在MFC的源文件appmodul.cpp中能看到這些代碼,那這個main怎么被MFC調用的呢,你看那注釋,是linkage to this module,也就是被鏈接器去調用的.準確說是被C-Runtime DLL,C運行時動態鏈接庫調用的.
調用main的順序
我們知道在MFC中能從代碼里看到的入口點是定義一個全局的繼承于CWinApp的類.比如CMyApp theApp;這樣定義下.在C++中全局變量是先于main被執行的,所以先初始化theApp后才接著調用main
?
2.針對第2個問題,main函數里具體的操作.
知道了有main函數,你心里可能有一絲安慰了.但還是有些覺得不安的是這main函數里的具體操作是否跟SDK中的一樣,是不是也來那么幾步,先注冊窗口再創建窗口之類的.
答案是MFC調用的main函數大概流程差不多是那樣,但實現細節很不一樣.我們看下上面說的AfxWinMain里面的內容是啥吧.你可以在winmain.cpp中看到詳細代碼.
把這個main函數簡化一下,做的操作大概是這樣,
AfxWinMain(...)
{
? //先通過一個全局函數獲得CWinApp和CWinThread的指針,因為調用main之前已經初始化了這兩個類.CMyApp初始化時也會初始化他的父類CWinApp,及父類的父類CWinThread
?? CWinThread* pThread = AfxGetThread();?
???CWinApp* pApp = AfxGetApp();
?
??? //這下面幾個函數就差不多是完成前面講的SDK中的所有步驟
?? pApp->InitApplication();
??? pThread->InitInstance();
??? pThread->Run();
?
??? AfxWinTerm(); //結束程序
???}
反正結束程序我們就不用管了,重點關心前面的三步,注冊窗口,創建窗口,還有消息分派.
前面的SDK程序中也恰好有函數InitApplication 注冊窗口, InitInstance創建并顯示窗口.而Run函數你猜想可能是分派消息的..其實大體思路還是沒錯,但實現細節還是有蠻多區別.
pApp->InitApplication();這函數實際上并沒有注冊窗口.注冊窗口,創建顯示窗口全是在pThread->InitInstance();這函數中完成,InitInstance是個虛函數,而且我們在自己的代碼中會重寫它.所以最后調用的是我們自己寫的那個InitInstance函數,這就是面向對象里多態的功能了啊.你指針最終指向對應的子類定義的函數.
BOOL CMyApp::InitInstance()
{
?m_pMainWnd = new CMyFrameWnd; //這張操作會注冊并創建窗口,m_pMainWnd就是返回的窗口句柄
m_pMainWnd->ShowWindow(m_nCmdShow); //顯示窗口
m_pMainWnd->UpdateWindow();
}
?
pThread->Run();是分派消息,你可以在thrdcore.cpp中查看CWinThreed的run函數的源碼,下面摘了一點點.
// acquire and dispatch messages until a WM_QUIT message is received.
for (;;)
{}
不過關于消息的處理MFC用到了消息映射機制,比如復雜.這里不討論了,反正大概就把CMyFrameWnd當成是窗口過程就行了.
?
MFC怎么封裝CreateWindow見: http://blog.csdn.net/weiwenhp/article/details/8796337
總結起來可以這樣簡單的說,MFC中有main函數,但是由系統去調用.然后main函數里面執行的操作差不多,只不過它是通過CWinApp和CWinThread的指針去調用一些相關的函數.而指針嘛由于調用了虛函數,所以用到了面向對象中的多態,于是轉來轉去的.然后最難的地方可能就是消息機制在這里更復雜一點了.不能簡單的與SDK中做一對一的對比.
總結
以上是生活随笔為你收集整理的MFC的Main函数跑哪去了的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 重装TCP/IP
- 下一篇: Optimizing Code with
