从CWnd::GetSafeHwnd实现得到的知识

在看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.\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, 0, "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( 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++对象模型》

 

posted @ 2017-04-03 15:28  shanql  阅读(346)  评论(0编辑  收藏  举报