VC6建单文档MFC,用OD跟踪进入MFC42D.dll中的MFC42D.#1190_?AfxWinMain@@YGHPAUHINSTANCE__@@0PADH@Z(AfxWinMain函数在MFC/SRC/WINMAIN.CPP中可看到源码).
5F4359D1 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4] 5F4359D4 8B02 MOV EAX,DWORD PTR DS:[EDX] ;EAX=004160E0,指向虚函数表 5F4359D6 8B4D FC MOV ECX,DWORD PTR SS:[EBP-4] ;ECX=this指针 5F4359D9 FF90 8C000000 CALL DWORD PTR DS:[EAX+8C]
004160E0 00402982 <JMP.&MFC42D.#2986_?GetRuntimeClass@CWinApp@@UBEPAUCRuntimeClass@@XZ> 004160E4 004010FF SD.004010FF 004160E8 0040297C <JMP.&MFC42D.#4492_?Serialize@CObject@@UAEXAAVCArchive@@@Z> 004160EC 00402976 <JMP.&MFC42D.#1285_?AssertValid@CWinApp@@UBEXXZ> 004160F0 00402970 <JMP.&MFC42D.#2021_?Dump@CWinApp@@UBEXAAVCDumpContext@@@Z> 004160F4 0040296A <JMP.&MFC42D.#3657_?OnCmdMsg@CCmdTarget@@UAEHIHPAXPAUAFX_CMDHANDLERINFO@@@Z> 004160F8 00402964 <JMP.&MFC42D.#3784_?OnFinalRelease@CCmdTarget@@UAEXXZ> 004160FC 0040295E <JMP.&MFC42D.#3367_?IsInvokeAllowed@CCmdTarget@@UAEHJ@Z> 00416100 00402958 <JMP.&MFC42D.#2431_?GetDispatchIID@CCmdTarget@@UAEHPAU_GUID@@@Z> 00416104 00402952 <JMP.&MFC42D.#3142_?GetTypeInfoCount@CCmdTarget@@UAEIXZ> 00416108 0040294C <JMP.&MFC42D.#3144_?GetTypeLibCache@CCmdTarget@@UAEPAVCTypeLibCache@@XZ> 0041610C 00402946 <JMP.&MFC42D.#3143_?GetTypeLib@CCmdTarget@@UAEJKPAPAUITypeLib@@@Z> 00416110 004010C3 SD.004010C3 00416114 00402940 <JMP.&MFC42D.#2339_?GetCommandMap@CCmdTarget@@MBEPBUAFX_OLECMDMAP@@XZ> 00416118 0040293A <JMP.&MFC42D.#2432_?GetDispatchMap@CCmdTarget@@MBEPBUAFX_DISPMAP@@XZ> 0041611C 00402934 <JMP.&MFC42D.#2341_?GetConnectionMap@CCmdTarget@@MBEPBUAFX_CONNECTIONMAP@@XZ> 00416120 0040292E <JMP.&MFC42D.#2585_?GetInterfaceMap@CCmdTarget@@MBEPBUAFX_INTERFACEMAP@@XZ> 00416124 00402928 <JMP.&MFC42D.#2473_?GetEventSinkMap@CCmdTarget@@MBEPBUAFX_EVENTSINKMAP@@XZ> 00416128 00402922 <JMP.&MFC42D.#3691_?OnCreateAggregates@CCmdTarget@@UAEHXZ> 0041612C 0040291C <JMP.&MFC42D.#2584_?GetInterfaceHook@CCmdTarget@@UAEPAUIUnknown@@PBX@Z> 00416130 00402916 <JMP.&MFC42D.#2481_?GetExtraConnectionPoints@CCmdTarget@@MAEHPAVCPtrArray@@@Z> 00416134 00402910 <JMP.&MFC42D.#2340_?GetConnectionHook@CCmdTarget@@MAEPAUIConnectionPoint@@ABU_GUID@@@Z> 00416138 00401023 SD.00401023 0041613C 0040290A <JMP.&MFC42D.#4408_?Run@CWinApp@@UAEHXZ> 00416140 00402904 <JMP.&MFC42D.#4215_?PreTranslateMessage@CWinThread@@UAEHPAUtagMSG@@@Z> 00416144 004028FE <JMP.&MFC42D.#4239_?PumpMessage@CWinThread@@UAEHXZ> 00416148 004028F8 <JMP.&MFC42D.#3826_?OnIdle@CWinApp@@UAEHJ@Z> 0041614C 004028F2 <JMP.&MFC42D.#3366_?IsIdleMessage@CWinThread@@UAEHPAUtagMSG@@@Z> 00416150 004028EC <JMP.&MFC42D.#2104_?ExitInstance@CWinApp@@UAEHXZ> 00416154 004028E6 <JMP.&MFC42D.#4229_?ProcessWndProcException@CWinApp@@UAEJPAVCException@@PBUtagMSG@@@Z> 00416158 004028E0 <JMP.&MFC42D.#4227_?ProcessMessageFilter@CWinThread@@UAEHHPAUtagMSG@@@Z> 0041615C 004028DA <JMP.&MFC42D.#2661_?GetMainWnd@CWinThread@@UAEPAVCWnd@@XZ> 00416160 004028D4 <JMP.&MFC42D.#1789_?Delete@CWinThread@@UAEXXZ> 00416164 004028CE <JMP.&MFC42D.#4130_?OpenDocumentFile@CWinApp@@UAEPAVCDocument@@PBD@Z> 00416168 004028C8 <JMP.&MFC42D.#1033_?AddToRecentFileList@CWinApp@@UAEXPBD@Z> 0041616C 004028C2 <JMP.&MFC42D.#3231_?InitApplication@CWinApp@@UAEHXZ> 00416170 004028BC <JMP.&MFC42D.#4415_?SaveAllModified@CWinApp@@UAEHXZ> 00416174 004028B6 <JMP.&MFC42D.#1860_?DoMessageBox@CWinApp@@UAEHPBDII@Z> 00416178 004028B0 <JMP.&MFC42D.#1880_?DoWaitCursor@CWinApp@@UAEXH@Z> 0041617C 004028AA <JMP.&MFC42D.#3702_?OnDDECommand@CWinApp@@UAEHPAD@Z> 00416180 004028A4 <JMP.&MFC42D.#5077_?WinHelpA@CWinApp@@UAEXKI@Z>
CWinApp继承关系 CObject CCmdTarget CWinThread CWinApp CWinApp VFTable +--------------- |+-------------- ||+------------- |||+------------ +0 ||||CObject::GetRuntimeClass() +4 ||||CObject::~CObject() +8 ||||CObject::Serialize() +0C ||||CObject::AssertValid() +10 ||||CObject::Dump() |||+------------ +14 |||CCmdTarget::OnCmdMsg() +18 |||CCmdTarget::OnFinalRelease() +1C |||CCmdTarget::IsInvokeAllowed() +20 |||CCmdTarget::GetDispatchIID() +24 |||CCmdTarget::GetTypeInfoCount() +28 |||CCmdTarget::GetTypeLibCache() +2C |||CCmdTarget::GetTypeLib() +30 |||CCmdTarget::GetMessageMap() +34 |||CCmdTarget::GetCommandMap() +38 |||CCmdTarget::GetDispatchMap +3C |||CCmdTarget::GetConnectionMap() +40 |||CCmdTarget::GetInterfaceMap() +44 |||CCmdTarget::GetEventSinkMap() +48 |||CCmdTarget::OnCreateAggregates() +4C |||CCmdTarget::GetInterfaceHook() +50 |||CCmdTarget::GetExtraConnectionPoints() +54 |||CCmdTarget::GetConnectionHook() ||+------------- +58 ||CWinThread::InitInstance() +5C ||CWinThread::Run() +60 ||CWinThread::PreTranslateMessage() +64 ||CWinThread::PumpMessage() +68 ||CWinThread::OnIdle() +6C ||CWinThread::IsIdleMessage() +70 ||CWinThread::ExitInstance() +74 ||CWinThread::ProcessWndProcException() +78 ||CWinThread::ProcessMessageFilter() +7C ||CWinThread::GetMainWnd() +80 ||CWinThread::Delete() |+-------------- +84 |CWinApp::OpenDocumentFile() +88 |CWinApp::AddToRecentFileList() +8C |CWinApp::InitApplication() +90 |CWinApp::SaveAllModified() +94 |CWinApp::DoMessageBox() +98 |CWinApp::DoWaitCursor() +9C |CWinApp::OnDDECommand() +A0 |CWinApp::WinHelp() +---------------
C++的虚函数是动态联编的,CWinThread.InitInstance()可能变成CWinApp.InitInstance();CWinThread.Run()就可能是CWinApp.Run()等等;因为重载可能地址为你重载后的地址,上面列表只是个参考。
根据MFC/Include/AFX.H中内容可以看出虚函数表和类中虚函数定义的顺序相同,CWinApp在MFC/Include/AFXWIN.H中.
///////////////////////////////////////////////////////////////////////////// // class CObject is the root of all compliant objects #ifdef _AFXDLL class CObject #else class AFX_NOVTABLE CObject #endif { public: // Object model (types, destruction, allocation) virtual CRuntimeClass* GetRuntimeClass() const; virtual ~CObject(); // virtual destructors are necessary // Diagnostic allocations void* PASCAL operator new(size_t nSize); void* PASCAL operator new(size_t, void* p); void PASCAL operator delete(void* p); #if _MSC_VER >= 1200 void PASCAL operator delete(void* p, void* pPlace); #endif #if defined(_DEBUG) && !defined(_AFX_NO_DEBUG_CRT) // for file name/line number tracking using DEBUG_NEW void* PASCAL operator new(size_t nSize, LPCSTR lpszFileName, int nLine); #if _MSC_VER >= 1200 void PASCAL operator delete(void *p, LPCSTR lpszFileName, int nLine); #endif #endif // Disable the copy constructor and assignment by default so you will get // compiler errors instead of unexpected behaviour if you pass objects // by value or assign objects. protected: CObject(); private: CObject(const CObject& objectSrc); // no implementation void operator=(const CObject& objectSrc); // no implementation // Attributes public: BOOL IsSerializable() const; BOOL IsKindOf(const CRuntimeClass* pClass) const; // Overridables virtual void Serialize(CArchive& ar); #if defined(_DEBUG) || defined(_AFXDLL) // Diagnostic Support virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif // Implementation public: static const AFX_DATA CRuntimeClass classCObject; #ifdef _AFXDLL static CRuntimeClass* PASCAL _GetBaseClass(); #endif };