前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Qt窗口关闭和应用程序停止是否调用析构函数的一些说明

Qt窗口关闭和应用程序停止是否调用析构函数的一些说明

作者头像
花狗Fdog
发布2021-06-17 19:36:30
2.2K0
发布2021-06-17 19:36:30
举报
文章被收录于专栏:花狗在Qt花狗在Qt

这几天一直在模仿QQ做一个即时通讯软件,过程不是很顺利,表现在窗口关闭,应用程序依旧存在,应用程序异常结束,关闭子窗口,主窗口跟着关闭,所以总结了一些内容,方便日后获取。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

如果对这个项目有兴趣的话可以前往GitHub:https://github.com/FdogMain/FdogInstantMessaging


main函数中,在栈上创建的窗口,关闭的时候自动调用析构函数,这种情况不可以使用this->setAttribute(Qt::WA_DeleteOnClose);,关闭时会出现异常,如果是在堆上创建,则可以使用this->setAttribute(Qt::WA_DeleteOnClose),调用析构函数时,不会有异常。

当关闭窗口时会调用close函数,这个函数发送一个关闭事件 QCloseEvent,接着窗口将会被隐藏,如果想实现关闭时进行询问,可以拦截QCloseEvent事件,也就是重写QCloseEvent,可以让用户来选择关闭,还是取消。

在不加Qt::WA_DeleteOnClose时,选择关闭,窗口将会消失,其实调用了hide,如果加了之后,除了调用hide,还会调用deleteLater方法来将窗口释放掉,在不加这个属性的情况下,close和hide,还有servisibel的功能是一样,只是会隐藏窗口对象而已,不会销毁对象。


在main,栈上面创建一个窗口A,关闭窗口A时,会调用析构函数。 如果在这个窗口A的构造函数中再创建一个窗口B,并且在A的析构函数中对B进行释放。

第一种形式:

MainWindow * b = new MainWindow();

当关闭窗口A,再关闭窗口B时,创建B的析构函数被调用,窗口A的析构函数被调用 (这种关闭方式有明显的卡顿,当关闭A,按照规则,B应该被关掉,释放,但是B窗口还显示在桌面,多次运行,发现还会存在A析构不执行的问题(析构中的打印语句并未被打印在控制台),所以这种方式存在问题)

反过来,当先关闭窗口B,再关闭窗口A,B的析构函数被调用,窗口A的析构函数被调用 (这种关闭方式无卡顿,实际上是B窗口被隐藏,并未主动执行析构,而在A的析构函数中被动执行,这也是为什么关闭B时,显示并未调用B析构,而关闭A时,才显示调用B析构的原因)

我们给窗口B添加Qt::WA_DeleteOnClose试一下(构造函数中添加setAttribute(Qt::WA_DeleteOnClose)),因为窗口B是窗口在堆上的,可以使用setAttribute(Qt::WA_DeleteOnClose)),

还是先关闭窗口A,再关闭窗口B,显示调用了窗口B的析构函数,然后出现异常,这个异常应该是重复析构B发送的异常。

把窗口A中关于窗口B释放的代码去掉,显示调用了窗口B的析构函数,调用窗口A的析构函数,但是没有出现异常(存在卡顿,多次运行,发现还会存在A析构不执行的问题(析构中的打印语句并未被打印在控制台))。

现在反过来,先关闭窗口B,由于窗口B设置了setAttribute(Qt::WA_DeleteOnClose))属性,立即执行了析构函数,接着关闭窗口A,如果不出意外的话,应该会出现异常,因为窗口B已经被释放,再在窗口A中再次释放B会报异常,把A中析构函数中的释放B的代码再次注释,运行,显示依次调用了窗口B的析构函数,窗口A的析构函数(无卡顿)。


第二种形式,指定父窗口

MainWindow * b = new MainWindow(this);

A窗口析构没有写释放B窗口的代码情况下:

关闭A窗口(被释放),B窗口跟着关闭(被释放)(无卡顿)。

关闭B窗口(只是隐藏),关闭A窗口(被释放)(无卡顿)。

再次试着给 b 添加setAttribute(Qt::WA_DeleteOnClose))属性,关闭B窗口,执行B析构,再关闭A,执行A的析构(无卡顿)。

关闭A窗口,执行A的析构,执行B的析构,并且B窗口被关闭(无卡顿)。

这里是因为QT的父子对象机制在起作用,原因就在于那个this。

当我们使用父对象来创建一个对象的时候 ,父对象会把这个对象添加到自己的子对象列表中。当这个父对象被删除的时候,它会遍历它的子对象类表并且删除每一个子对象,然后子对象们自己再删除它们自己的子对象,这样递归调用直到所有对象都被删除,所以如果new出来的控件,如果有指定父对象,无需我们手动删除。

还有一个发现,就是其他控件如果指定A窗口作为父窗口,是会被嵌入在A窗口中的,但是MainWindow这个类的窗口不会被嵌入 反过来则不然。

但是上面这些仅仅是在基本情况下,当我把窗口属性设置为无边框,无任务栏之后等等不同属性之后,再次关闭窗口,析构函数不会被自动调用,换句话说就是只是窗口关闭了,但是应用程序本身还没有关闭,最明显的特征就是当你关闭了窗口,qt的应用程序输出窗口还是显示着红色的方块而不是绿色的三角。

这个时候可以在你想要关闭的地方添加下列代码,应用程序就会被关闭。

    QApplication* app;
    app->quit();

还有一种情况就是在MainWindow中创建widget窗口,但是一关闭最后一个widget,MainWindow就会被关闭,是不是不可思议,在没找到解决方案之前,我只能判断是不是最后一个widget,如果是我就隐藏,而不是关闭,举个例子。

例如qq 主界面是MainWindow 双击好友生成widget窗口。

当关闭这些widget窗口到最后一个的时候,主窗口会跟着关闭,出现这种症状的原因之一,是设置了窗口的属性

也就是使用了这个函数setWindowFlags(),一不做二不休,将这个widget窗口再添加一个属性setWindowFlag(Qt::CoverWindow);

这个问题可能会不存在了~

还有一个问题就是关闭窗口,可能会报程序异常结束,这个错误也和main中窗口创建的位置有关。


本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-06-12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
即时通信 IM
即时通信 IM(Instant Messaging)基于腾讯二十余年的 IM 技术积累,支持Android、iOS、Mac、Windows、Web、H5、小程序平台且跨终端互通,低代码 UI 组件助您30分钟集成单聊、群聊、关系链、消息漫游、群组管理、资料管理、直播弹幕和内容审核等能力。适用于直播互动、电商带货、客服咨询、社交沟通、在线课程、企业办公、互动游戏、医疗健康等场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档