在看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, , "Warning: failed to load menu for CFrameWnd.\n");
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, , "Warning: failed to create CFrameWnd.\n");
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( )
{
cout << "TestClass()" << endl;
} virtual ~TestClass()
{
cout << "~TestClass()" << endl;
} //this==NULL时,未使用本类变量
int GetInt()
{
if ( this == NULL )
{
return ;
}
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 ;
}

TODO: 有空要学习下《深度探索C++对象模型》

05-27 14:42