在看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. SQL Server常用系统表

    1.查询当前数据库中的用户表 select *from sysobjects where xtype='U'; 2.获取SQL Server允许同时用户连接的最大数 SELECT @@MAX_CONN ...

  2. win10系统架构调用

    操作系统模型 操作系统有两种模式: 用户模式 内核模式 当用户模式调用系统服务时,CPU执行一个特殊的指令以切换到内核模式(Ring0),当系统服务调用完成时,操作系统切换回用户模式(Ring3).  ...

  3. jdk并发工具包之锁

    1.cynchronized扩展:可重锁入ReentrantLock ReentrantLock是通过cas算法实现的 RenntrantLock lock=new ReentrantLock(); ...

  4. 【问】Windows下C++局部变量在内存中的分布问题

    原本是为了看看C++对象模型中子对象赋值给一个父对象和父类型指针指向的域时,到底会不会切割,就打开codebloks写了下面的代码,编译器选的是GNU. #define DEBUG(X) std::c ...

  5. android 编译问题解决

    1.android4.2.2 '/root/origin_android/mokesoures/out/target/common/obj/APPS/ApplicationsProvider_inte ...

  6. EF6&EFCore 注册/使用实体类的正确姿势

    首先回顾下EF中常规使用流程 1.新建实体类以及实体配置(data annotation或fluent api) [Table("Users")] public class Use ...

  7. WPF实现ScrollViewer滚动到指定控件处

    在前端 UI 开发中,有时,我们会遇到这样的需求:在一个 ScrollViewer 中有很多内容,而我们需要实现在执行某个操作后能够定位到其中指定的控件处:这很像在 HTML 页面中点击一个链接后定位 ...

  8. IOS获取当前地理位置文本

    本文转载至  http://blog.csdn.net/lvxiangan/article/details/28101119   以下内容摘抄自网络,著作权属于原作者 方法1:使用ios自带联网查询功 ...

  9. python 基础 1.5 python数据类型(四)--字典常用方法示例

    一. 字典 #字典 dict1 = {'name':'lzc','age':'20','sex':'man'} print dict1 print type(dict1) >>> { ...

  10. EasyNVR无插件流媒体服务器前端技术防止重复提交的方法

    现在随着接触EasyNVR时间越来越长,越发的觉得EasyNVR真的是一个"神器".从功能上来说自身不仅可以拉出来使用(具体功能搜索EasyNVR一定有惊喜!),也可以作为设备端与 ...