在看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++对象模型》

从CWnd::GetSafeHwnd实现得到的知识的更多相关文章

  1. CWnd与HWND的简单辨析

    今天在写一个小的网络应用,需要用到HWND类型的一个参数.而程序中有的“窗口操作句柄”只有一个CWnd类型的指针.这俩不都是“窗口句柄”么?而且反正都是地址直接转换使用如何?结果出现了调用失效的情况. ...

  2. GetSafeHwnd()函数解释[转]

    当我们想得到一个窗口对象(CWnd的派生对象)指针的句柄(HWND)时,最安全的方法是使用GetSafeHwnd()函数,通过下面的例子来看其理由: CWnd *pwnd = FindWindow(“ ...

  3. 为什么要使用GetSafeHwnd()函数

    当我们想得到一个窗口对象(CWnd的派生对象)指针的句柄(HWND)时,最安全的方法是使用GetSafeHwnd()函数,通过下面的例子来看其理由: CWnd *pwnd = FindWindow(“ ...

  4. VC++ GetSafeHwnd用法

    GetSafeHwnd HWND GetSafeHwnd() const; 当我们想得到一个窗口对象(CWnd的派生对象)指针的句柄(HWND)时,最安全的方法是使用GetSafeHwnd()函数. ...

  5. ID--HANDLE--HWND三者之间的互相转换

    利用PreTranslateMessage,响应按钮控件的按下(WM_LBUTTONDOWN)和松开(WM_LBUTTONUP)   VC的button控制只有两个事件,一个是单击事件,一个事双击事件 ...

  6. 【转】MFC窗口句柄各类指针获取函数

    原文网址:http://www.pythonschool.com/CPP_JHK/5003.html 获取所在类窗口的句柄 this->m_hwnd; // this是一个指针,指向当前类的实例 ...

  7. C++ MFC常用函数(转)

    WinExec() ExitWindowsEx() GlobalMemoryStatus() GetSystemInfo() GetSystemDirectory() GetWindowsDirect ...

  8. Delphi下OpenGL2d绘图(06)-画图(多窗口、多视图、多个DC)

    一.前言 在学习OpenGL的过程中,发现很多函数都是全局的.前面几章中都是在一个窗口DC中画图,那么要在多个窗口画图,需要怎么处理呢?网上方法有多种,这里采用其中一种,利用wglMakeCurren ...

  9. MFC常用函数总结

    1.MFC编辑框.静态文本框相关的常用函数 <1>GetDlgItemText(ID ,str) 作用:从对话框中获取文本 第一个参数为要获取的编辑框(或者静态文本框.单选按钮等可以显示内 ...

随机推荐

  1. 字符串各个字符ASCII值加5

    程序实现目标: 输入一个字符串,将其各个字符对应的ASCII值加5后,输出结果 程序要求:该字符串只包含小写字母,若其值加5后的字符值大于'z',将其转换成从a开始的字符. 分析:问题归结为三点: 1 ...

  2. js的常用小技巧

    //类对象转成数组 var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));   ...

  3. ubantu 下 修改mysql 默认编码

    启动mysql后,以root登录mysql root@Eadgar-virtual-machine:~# mysql -uroot -proot mysql> show variables li ...

  4. .NET C# 【小技巧】控制台程序,运行是否弹出窗口选择!

    选中控制台程序项目,右键→属性→应用程序栏→输出类型: 1.Windows 应用程序(不弹出提示框)! 2.控制台应用程序(弹出提示框)! 3.类库(类库生成dll,是不能直接运行的,类库供应用程序调 ...

  5. 讲真,你是因为什么才买华为P20系列手机!

    华为P20系列手机上市两个半月发货600万台!600万台?!看到这个亮瞎我钛合金狗眼的数据,且容我掰着手指脚趾算一下,算了,还是容我毫不夸张的感叹一句吧:华为做手机不用桨,不需风,全靠“浪”……. 两 ...

  6. POJ 1787 Charlie&#39;s Change

    多重背包 可行性+路径记录 题意是说你要用很多其它的零钱去买咖啡.最后输出你分别要用的 1,5 ,10 .25 的钱的数量. 多重背包二进制分解.然后记录下 这个状态.最后逆向推就可以. #inclu ...

  7. 【转载】【selenium+Python WebDriver】之元素定位

    总结: 感谢: “煜妃”<Selenuim+Python之元素定位总结及实例说明> “Huilaojia123”<selenium WebDriver定位元素学习总结> “上海 ...

  8. 为CentOS配置网易163的yum源

    Yum (Yellow dog Updater, Modified)是一个基于 RPM 包管理的字符前端软件包管理器.能够从指定的服务器自动下载 RPM 包并且安装,可以处理依赖性关系,并且一次安装所 ...

  9. RedHat7 防火墙设置以及端口设置

    1.查看防火墙状态,root用户登录,执行命令systemctl status firewalld 2.开启防火墙:systemctl start firewalld 3.关闭防火墙:systemct ...

  10. jQuery中slideToggle()的详细使用方法和解释

    $(selector).slideToggle(speed,callback) 参数       speed和callback Speed  可选.规定元素从隐藏到显示的速度,默认‘normal’可能 ...