对话框类对象的自销毁与外销毁

原创 2003年06月06日 07:51:00

1         前言<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

MFC开发过程中起始有很多的细节指出可以作为一种模式,为今后的MFC开发工作做实际指导。本文介绍无模式对话框的内存管理。

1.1        约定

l        五号宋体斜字体表示:特定定义;

l        小五号Arial字体表示:VC++代码使用

l        五号楷体字体表示:类名称、类对象

2         正文

无模式对话框Modeless Dialog。之所以称为无模式,是因为无模式对话框允许用户同时操作其他窗口,这样窗口就可以作为工具窗口在程序主要窗口之外提供额外的功能,分离了各个对话框的功能。最常见的是Windows操作系统层次的窗口,例如资源管理器,我的电脑,Word。本文介绍的是更下一层次的窗口,例如Word属性设置对话框。

无模式对话框的创建通过三步曲完成:new -> CreateWindow() -> ShowWindow(SW_SHOW)无模式对话框的销毁通常有两种方法,一是在对话框的OnNcDestroy()函数中用delete this销毁自身内存,二是在外界用delete pdlg来清空内存。一下我们简称第一种方法为自销毁方法,称第二种方法为外销毁方法。

事实上两种方法创建的对话框的使用方式完全相同。他们的不同之处仅在于内存由谁来负责回收。

面向对象的C++的基本内存管理思想是由对象自身负责内存的回收,类的构造函数和析构函数正是这种思想的直接实现者。构造函数中应该包含所有对象中内存的分配逻辑,析构函数中包含所有对象中内存的释放逻辑。这样,不管对象中包含了如何复杂的内存存储结构,外界的管理方法都一样简单:对于静态对象,只需简单的对象声明即可,而对于动态对象,调用new/delete,就可以为对象分配/回收内存。

但关键问题是C++的指针特性带来了问题。指针特性带来了动态内存分配能力,但它是一把双刃剑,大部分的内存泄漏都与此有关。对于静态对象,构造和析构对象的代码都被作为可执行文件的一部分硬性编译到了可执行文件中,应用程序肯定会执行这一段代码,内存肯定不可能泄漏(除非系统有不测风云)。而动态对象必须由程序员负责调用delete来手动销毁,这是问题的关键所在,许多粗心的程序员常常会因为忘记了调用delete而导致内存泄漏而为此感到痛心疾首,或者因为多调用了delete后出现了严重的异常导致程序崩溃。我对那个Windows下的画着红色X号对话框是如此的记忆深刻,甚至我一看见他就觉得心惊胆战、浑身不爽。

如果你使用具有自销毁能力的对话框类创建模式对话框,你也同样将不得不面对这样的问题,那个红色X号对话框就会象恶魔一样缠着你。模式对话框使用DoModal()函数创建Windows窗口,在DoModal()返回的过程中,MFC 框架将发送NC_DESTROY消息到窗口,窗口在接受到该消息后执行窗口类的OnNcDestroy()函数。由于该类应用了自销毁方法,此时将调用delete this,也就是说窗口类对象的内存此时就已经被(自)清空了。这是第一次调用类的析构函数。然后,因为模式对话框是静态对象,应用程序将再一次执行析构函数……不用我说,你知道什么来了吧?那个画着红色X号的对话框!恐怖啊!

“哦哟!其实我对它应用自销毁方法,当然就是为了使用无模式对话框!”。也许你会这样为你的自销毁对话框类辩解。

呵呵,让我为你的这句话做个直译:自销毁的对话框类只能创建为无模式对话框。是的,对于你自己的程序,对于目前的程序,当然不需要考虑这么多。

但是,更重要的原因是,使用了自销毁,一旦程序需要这个对话框表现为模式对话框,你将不得不直接修改该对话框类的代码。如果你把该类作为二进制的组件交给别人使用,那么对于那些需要使用模式对话框的人,这个类将毫无用处。

如果使用外销毁方法,那么这些问题都是不存在的,你需要记住的是一定要手动调用delete pdlg。这样虽然多了无数次的delete pdlg调用,但是你可以清楚的知道什么地方创建了它,然后又在什么地方销毁了它,这一切都被你牢牢地掌握着。而且,你可以根据不同的需要,利用该对话框类创建模式和无模式对话框,这事实上提高了程序的灵活性和可扩展性。

3         结论

自销毁对话框类限制了对话框的创建模式,降低了程序的灵活性和可扩展性。而外销毁对话框类没有这些限制。现代程序的编写风格更加重视程序扩展性和灵活性,所以,我建议在程序中使用外销毁方法。

Dialog对象在activity中如果声明为局部变量,则可以被回收

如果在activity中生命一个全局的dialog对象,则该对象不会被回收。因此在调用activity的finish方法时,该dialog对象如果没有销毁,则会在控制台报错。...
  • mr_orange_klj
  • mr_orange_klj
  • 2015年01月28日 23:18
  • 561

AlertDialog cancel() 销毁窗口流程解析

今天来法分析AlertDialog cancel() 销毁窗口流程。前面文章说了其实activity和dialog都是通过window对象来管理视图的。所以我们可以从AlertDialog销毁过程来了...
  • mhhyoucom
  • mhhyoucom
  • 2017年09月13日 14:49
  • 600

对话框类对象的自销毁与外销毁

无模式对话框即Modeless Dialog。之所以称为无模式,是因为无模式对话框允许用户同时操作其他窗口,这样窗口就可以作为工具窗口在程序主要窗口之外提供额外的功能,分离了各个对话框的功能。最常见的...
  • rachel_cy
  • rachel_cy
  • 2006年09月07日 09:37
  • 821

关于子对话框的创建与销毁

1.显示对话框 1.1显示模式对话框: CDialogDemo dlg; dlg.DoModal(); 1.2 显示非模式对话框: CDialogDemo *dlg=new CDialogDe...
  • shenziheng1
  • shenziheng1
  • 2016年11月21日 10:31
  • 717

C++对象产生和销毁的顺序

C++中,如果对象是用new操作生成的,那么它的空间被分配在堆(Heap)上,只有显示地调用delete(或delete[])才能调用对象的析构函数并释放对象的空间。那么,在程序的其他存储区(全局/静...
  • K346K346
  • K346K346
  • 2015年10月27日 15:15
  • 2177

MFC对话框的创建和销毁顺序

非 模态对话框相对于模态对话框,他的创建和销毁过程和模态对话框有一定的区别,先看一下MSDN的原文:When   you   implement   a   modeless   dialog   b...
  • leaf6094189
  • leaf6094189
  • 2012年05月28日 14:36
  • 3760

关于模态对话框的销毁问题

模态对话框,在一些应用程序中经常有必要存在,但也有许多的问题。问题一:阻塞消息的处理。这个问题比较好处理。问题二:即使在单线程的程序中,也会导致程序的异步执行。工作中,我遇到过这种类似的问题。控制模块...
  • vptr_grid
  • vptr_grid
  • 2005年03月24日 09:39
  • 1014

MFC非模态对话框和模态对话框销毁的方法

  • liuyi1207164339
  • liuyi1207164339
  • 2015年06月29日 14:30
  • 1258

十一、Qt新对话框创建与销毁

模态对话框就是指在子对话框弹出时,焦点被强行集中于该子对话框,子对话框不关闭,用户将无法操作其他的窗口。非模态相反,用户仍然可以操作其他的窗口,包括该子对话框的父对话框。 如果从线程角度来讲,模...
  • chchlh
  • chchlh
  • 2014年01月17日 16:37
  • 3437

MFC对话框创建和销毁窗口时,函数的调用顺序

以下是一点资料供参考,非模态对话框的销毁顺序:MFC应用程序中处理消息的顺序1.AfxWndProc()      该函数负责接收消息,找到消息所属的CWnd对象,然后调用AfxCallWndProc...
  • jonathandj
  • jonathandj
  • 2009年06月29日 13:51
  • 9448
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:对话框类对象的自销毁与外销毁
举报原因:
原因补充:

(最多只允许输入30个字)