我們都知道MFC初始化的程序: CWinApp中的InitInstance是入口函式,一般是我們寫個派生類繼承他,再重寫InitInstance該函式。
再定義一個全域的物件。但我沒搞明白CWinApp類,他是如何呼叫我派生類里面的InitInstance函式。
很困惑。求大神指點
最好有個簡單的例子說明一下程序。
uj5u.com熱心網友回復:
__tmainCRTStartup首先呼叫_initterm來呼叫全域物件的建構式,然后CWinApp::CWinApp會把自己的地址存到一個全域的指標里面去(所以不能有兩個全域的CWinApp物件)然后呼叫CRT提供的WinMain ,這個會呼叫AfxWinMain,里面會呼叫這個全域的指標。至于你的InitInstance呼叫是因為InitInstance被宣告成為了虛函式。
uj5u.com熱心網友回復:
#include<afxwin.h>
class CMyApp : public CWinApp
{
virtual BOOL InitInstance()
{
return TRUE;
}
};
CMyApp theApp;
就因為宣告成了虛函式,CWinApp就能呼叫派生類里面實作的虛函式?
uj5u.com熱心網友回復:
我看頭檔案里面,他也不是一個純虛函式uj5u.com熱心網友回復:
用基類指標呼叫派生類的虛函式這功能叫做多型。如果你學了C++,老師一定會講多型的。CWinApp派生自CWinThread,CWinThread::InitInstance是虛函式。你的派生類里是不是再加virtual無所謂,只要函式的簽名和基類里的虛函式完全一樣,自動多載基類的虛函式,除非中間有類在多載這個虛函式的時候加了final關鍵字禁止派生類再多載這個函式。
uj5u.com熱心網友回復:
基類指標,需要派生類的指標進行實體化后,才能呼叫派生類的虛函式吧?
派生類的實體化的指標地址從何而來?
uj5u.com熱心網友回復:
在函式中設定一個斷點, F5除錯啟動, 停到斷點后 一層層查看呼叫堆疊關系分析uj5u.com熱心網友回復:

就這么幾個步驟
uj5u.com熱心網友回復:
實體的 虛函式表 有 自己的 虛函式,uj5u.com熱心網友回復:
基類的 虛函式表 有 自己的 虛函式1 如果 派生類 沒有 多載 基類的 虛函式,那么 派生類 的 虛函式表 保留 基類的 虛函式。
2 如果 派生類 多載 了基類的 虛函式,那么派生類 的 虛函式表 存有 自己的 虛函式,
3 派生類 呼叫 虛函式,就是 呼叫 虛函式表 中的 虛函式,
uj5u.com熱心網友回復:
大牛,能給個簡易的例子,說明一下不
uj5u.com熱心網友回復:
搜索“虛函式表”uj5u.com熱心網友回復:
擦,打個斷點看下就知道了,還要問人。uj5u.com熱心網友回復:
工程名cpp的 全域變數
CTestApp theApp;
appmodule.cpp
extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine, int nCmdShow)
#pragma warning(suppress: 4985)
{
// call shared/exported WinMain
return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
winmain.cpp,注意CWinApp的基類是CWinThread
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine, int nCmdShow)
{
ASSERT(hPrevInstance == NULL);
int nReturnCode = -1;
CWinThread* pThread = AfxGetThread();
CWinApp* pApp = AfxGetApp();
// AFX internal initialization
if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
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();
InitFailure:
#ifdef _DEBUG
// Check for missing AfxLockTempMap calls
if (AfxGetModuleThreadState()->m_nTempMapLock != 0)
{
TRACE(traceAppMsg, 0, "Warning: Temp map lock count non-zero (%ld).\n",
AfxGetModuleThreadState()->m_nTempMapLock);
}
AfxLockTempMaps();
AfxUnlockTempMaps(-1);
#endif
AfxWinTerm();
return nReturnCode;
}
instance是虛函式,所以會呼叫派生類的instance
BOOL CTestApp::InitInstance()
{
// 如果一個運行在 Windows XP 上的應用程式清單指定要
// 使用 ComCtl32.dll 版本 6 或更高版本來啟用可視化方式,
//則需要 InitCommonControlsEx()。否則,將無法創建視窗。
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// 將它設定為包括所有要在應用程式中使用的
// 公共控制元件類。
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
AfxEnableControlContainer();
// 創建 shell 管理器,以防對話框包含
// 任何 shell 樹視圖控制元件或 shell 串列視圖控制元件。
CShellManager *pShellManager = new CShellManager;
// 標準初始化
// 如果未使用這些功能并希望減小
// 最終可執行檔案的大小,則應移除下列
// 不需要的特定初始化例程
// 更改用于存盤設定的注冊表項
// TODO: 應適當修改該字串,
// 例如修改為公司或組織名
SetRegistryKey(_T("應用程式向導生成的本地應用程式"));
CTestDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: 在此放置處理何時用
// “確定”來關閉對話框的代碼
}
else if (nResponse == IDCANCEL)
{
// TODO: 在此放置處理何時用
// “取消”來關閉對話框的代碼
}
// 洗掉上面創建的 shell 管理器。
if (pShellManager != NULL)
{
delete pShellManager;
}
// 由于對話框已關閉,所以將回傳 FALSE 以便退出應用程式,
// 而不是啟動應用程式的訊息泵。
return FALSE;
}
對話框的Domodal把訊息佇列創建起來,UI執行緒跑起來,并且阻塞住winmain函式。
CTestDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
uj5u.com熱心網友回復:
當一個視窗關閉時WM_CLOSE,WM_DESTROY,WM_QUIT死回圈訊息佇列得收到WM_QUIT得以退出,DoModal函式得以回傳。
樓主想知道MFC框架如何搭建的,應該去學下《windows程式設計》 《設計模式》c++的基本知識。
必備的閱讀利器:VC助手插件
必須知道的知識:VS除錯模式,MFC作為靜態庫的時候,可以單步閱讀MFC框架所有原始碼!!
不要被專家誤導,c++是最容易入魔的語言,因為c++的偽專家太多了!
明白c++的優勢,明白c++的不足。
不要被MFC框架束縛,MFC是很古老的框架,有值得學習的地方,但是并不優雅。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/67026.html
標籤:基礎類
