在看MFC源码的过程中,有个地方一直不解,看如下代码
BOOL CFrameWnd::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, LPCTSTR lpszMenuName, DWORD dwExStyle, CCreateContext* pContext) { HMENU hMenu = NULL; if (lpszMenuName != NULL) { // load in a menu that will get destroyed when window gets destroyed HINSTANCE hInst = AfxFindResourceHandle(lpszMenuName, ATL_RT_MENU); if ((hMenu = ::LoadMenu(hInst, lpszMenuName)) == NULL) { TRACE(traceAppMsg, 0, "Warning: failed to load menu for CFrameWnd. "); PostNcDestroy(); // perhaps delete the C++ object return FALSE; } } m_strTitle = lpszWindowName; // save title for later if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext)) { TRACE(traceAppMsg, 0, "Warning: failed to create CFrameWnd. "); if (hMenu != NULL) DestroyMenu(hMenu); return FALSE; } return TRUE; }
注意Create函数参数pParentWnd如果传NULL进来,pParentWnd->GetSafeHwnd并不会报错。开始一看,吓我一大跳,怎么不出现内存访问违规呢,奇怪了。经过试验,还是自己的知识太欠缺了啊。
原因还得在代码中找,看下GetSafeHwnd的实现, 内部判断了this==NULL(第一次知道还可以这样用)
_AFXWIN_INLINE HWND CWnd::GetSafeHwnd() const { return this == NULL ? NULL : m_hWnd; }
以下是试验代码:
#include <iostream> using namespace std; class TestClass { public: TestClass():m_nInt( 222 ) { cout << "TestClass()" << endl; } virtual ~TestClass() { cout << "~TestClass()" << endl; } //this==NULL时,未使用本类变量 int GetInt() { if ( this == NULL ) { return 888; } return m_nInt; } //函数引用此类变量 int GetInt2() { return m_nInt; } private: int m_nInt; }; int main() { TestClass* pTest = NULL; //this==NULL时,未使用本类变量,故可正常调用 int nRet = pTest->GetInt(); //this==NULL时,使用本类变量, //而对象并不存在,内存访问违规!!! int nRet2 = pTest->GetInt2(); return 0; }
TODO: 有空要学习下《深度探索C++对象模型》