Qt初识_对象树

个人主页:C++忠实粉丝
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创

Qt初识_对象树

收录于专栏【Qt开发】
本专栏旨在分享学习Qt的一点学习笔记,欢迎大家在评论区交流讨论💌

目录

什么是对象树 

为什么要引入对象树? 

​代码示例


什么是对象树 

在 Qt 中创建很多对象的时候会提供一个 Parent 对象指针,下面来解释这个 parent 到底是干什么的。

• QObject 是以对象树的形式组织起来的。

当创建一个 QObject 对象时,会看到 QObject 的构造函数接收一个 QObject 指针作为参数,这个参数就是 parent,也就是父对象指针。

这相当于,在创建 QObject 对象时,可以提供一个其父对象,我们创建的这个 QObject 对象会自动添加到其父对象的 children() 列表。

当父对象析构的时候,这个列表中的所有对象也会被析构。(注意,这里的父对象并不是继承意义上的父类!)

这种机制在 GUI 程序设计中相当有用。例如,一个按钮有一个 QShortcut(快捷键)对象作为其子对象。当删除按钮的时候,这个快捷键理应被删除。这是合理的。 

• QWidget 是能够在屏幕上显示的一切组件的父类。

QWidget 继承自 QObject,因此也继承了这种对象树关系。一个孩子自动地称为父组件的一个子组件。因此,它会显示在父组件的坐标系统中,被父组件的边界裁剪。例如,当用户关闭一个对话框的时候,应用程序将其删除,那么我们希望属于这个对话框的按钮、图标等应该一起被删除。事实就是如此,因为这些都是对话框的子组件。

当然,我们也可以自己删除子对象,它们会自动从其父对象列表中删除。比如,当我们删除了一个工具栏时,其所在的主窗口会自动将该工具栏从其子对象列表中删除,并且自动调整屏幕显示。

为什么要引入对象树? 

Qt 引入对象树的概念,在一定程度上解决了内存问题。

当一个 QObject 对象在堆上创建的时候,Qt 会同时为其创建一个对象树。不过,对象树中对象的顺序是没有定义的。这意味着,销毁这些对象的顺序也是未定义。

任何对象树中的 QObject 对象 delete 的时候,如果这个对象有 parent,则自动将其从 parent 的 children() 列表中删除;如果有孩子,则自动 delete 每一个孩子。Qt 保证没有 QObject 会被 delete 两次,这是由析构顺序决定的。 

如果 QObject 在栈上创建,Qt 保持同样的行为。正常情况下,这也不会发生什么问题。比如下面的代码片段: 

作为父组件的 window 和作为子组件的 quit 都是 QObject 的子类(事实上,它们都是 QWidget 的子类,而 QWidget 是 QObject 的子类)。这段代码是正确的,quit 的析构函数不会被调用两次,因为标准 C++ 要求,局部对象的析构顺序应该按照其创建顺序的相反过程。因此,这段代码在超出作用域时,会调用 quit 的析构函数,将其从父对象 window 的子对象列表中删除,然后才会调用 window 的析构函数。

但是,如果我们使用下面的代码: 

 

 情况又有所不同,析构顺序就有了问题。我们看到,在上面的代码中,作为父对象的 window 会首先被析构,因为它是最后一个被创建的对象。在析构过程中,它会调用子对象列表中每一个对象的析构函数,也就是说,quit 此时就被析构了。然后,代码继续执行,在 window 析构之后,quit 也会被析构,因为 quit 也是一个局部变量,在超出作用域的时候当然也需要析构。但是,这时候已经是第二次调用 quit 的析构函数了,C++ 不允许调用两次析构函数,因此,程序崩溃了。

由此我们看到,Qt 的对象树机制虽然在一定程度上解决了内存问题,但是也引入了一些值得注意的事情。这些细节在今后的开发过程中很有可能时不时跳出来烦扰一下,所以,我们最好从开始养成好习惯。

在 Qt 中,尽量在构造的时候就指定 parent 对象,并且大胆在堆上创建。 

Qt对象树如图: 

代码示例

1、创建一个新工程并编译运行,生成如下窗口;(如果还不会的同学,可以参考这篇博客,超级详细:使用Qt Creator创建项目-CSDN博客)

2、选中工程名,鼠标右键 ---> “add new” (或 “添加新文件”)

 

3、选择 “choose“ ,弹出如下界面;

4、点击 ”下一步“,弹出如下对话框;

5、点击 ”完成“ 之后,手动创建类的头文件以及源文件会自动添加到目标工程中; 

6、修改头文件

7,编写源文件

8、编译并运行

 9、当关闭弹出的对话框时,就会自动调用按钮的析构函数

(这里不知道怎么回事 Debug没有打印出来, 用了之前的图)

 

10、执行结果分析:

对象树确保的是先释放子节点的内存,后释放父节点的内存。

而析构函数的调用顺序则不一定遵循上述要求,因此看到子节点的析构执行顺序反而在父节点析构顺序之后。

注意:调用析构函数和释放内存并非是同一件事情。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/63581.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

排序算法(3):插入排序

问题 排序 [30, 24, 5, 58, 18, 36, 12, 42, 39] 插入排序 插入排序将序列分为已排序和未排序两部分,每次从未排序部分取出第一个元素,插入到已排序部分的适当位置。重复此过程直到所有元素排序完成。 图解 初始化第一个元素为已排序部分&#xff0…

Java版-图论-最小生成树-Kruskal算法

实现描述 为了造出一棵最小生成树,我们从最小边权的边开始,按边权从小到大依次加入,如果某次加边产生了环,就扔掉这条边,直到加入了 n-1 条边,即形成了一棵树。 实现代码 首选我们对所有的边&#xff0c…

SORT算法详解及Python实现

目录 SORT算法详解及Python实现第一部分:SORT算法概述与原理1.1 SORT算法简介1.2 应用场景1.3 算法流程 第二部分:数学公式与主要模块2.1 卡尔曼滤波模型2.2 目标关联与匈牙利算法2.3 新建与移除机制 第三部分:Python实现:SORT算法…

传奇996_53——后端ui窗口局部刷新

描述:一个大窗口,点击某个键,弹出小窗口。 小窗口中将msg存进变量中 大窗口中判断一个参数是否为null,如果不为null,说明界面不是第一次打开,而是被刷新了。就加上小窗口的那个变量 有时小窗口中还有其他…

深入解析 Spring Security —— 打造高效安全的权限管理体系

目录 前言1. 初识 Spring Security1.1 Spring Security 的两大核心功能1.2 Spring Security 的主要特点 2. 配置 Spring Security2.1 配置类概述2.2 基础配置示例2.3 示例解析 3. Spring Security 的进阶功能3.1 自定义用户服务3.2 注解式权限控制3.3 动态权限控制 4. 实战应用…

JetBrains IDE(IDEAWebStorm)配置GitHub Copilot

关于 GitHub Copilot 和 JetBrains IDE GitHub Copilot 在编写代码时提供 AI 对程序员的自动完成样式的建议。 有关详细信息,请参阅“关于 GitHub Copilot Individual”。 如果使用 JetBrains IDE,可以直接在编辑器中查看并合并来自 GitHub Copilot 的…

OLLAMA+FASTGPT+M3E 大模型本地化部署手记

目录 1.安装ollama 0.5.1 2.下载大模型 qwen2.5 3b 3.开启WSL 4.更新wsl 5.安装ubuntu 6.docker下载 6.1 修改docker镜像源 6.2 开启WSL integration 7.安装fastgpt 7.1 创建fastgpt文件夹 7.2 下载fastgpt配置文件 8.启动容器 9.M3E下载 9.1 下载运行命令 9.2…

Go的Gin比java的Springboot更加的开箱即用?

前言 隔壁组的云计算零零后女同事,后文简称 云女士 ,非说 Go 的 Gin 框架比 Springboot 更加的开箱即用,我心想在 Java 里面 Springboot 已经打遍天下无敌手,这份底蕴岂是 Gin 能比。 但是云女士突出一个执拗,非我要…

神经网络中的过拟合问题及其解决方案

目录 ​编辑 过拟合的定义与影响 过拟合的成因 1. 模型复杂度过高 2. 训练数据不足 3. 训练时间过长 4. 数据特征过多 解决方案 1. 数据增强 2. 正则化 3. Dropout 4. 提前停止 5. 减少模型复杂度 6. 集成学习 7. 交叉验证 8. 增加数据量 9. 特征选择 10. 使…

Pull down筛靶策略丨筛选药物与潜在靶蛋白之间相互作用的体外技术

小分子药靶筛选的Pull down实验是一种有效的筛选药物与潜在靶蛋白之间相互作用的体外技术。利用生物分子之间的亲和力原理,将生物素标记的小分子化合物固定在链霉亲和素的磁珠上,与蛋白裂解液进行孵育,孵育结束后与小分子结合的蛋白可以通过质…

文件上传下载性能优化

客户端与服务器之间数据交换的效率取决于文件传输的性能。通过数据压缩和断点续传可以实现文件传输和网络请求中的性能优化。这两种方式可以减少宽带占用,提高传输效率,从而达到提升数据交换性能。 上传下载接口 request模块主要给应用提供上传下载文件…

通过交叉相关性在大估计误差存在的情况下进行时间延迟估计

这篇论文的主要结论包括以下几点: 阈值效应:随着后向积分信噪比(SNR)的降低,互相关器在时间延迟估计中表现出阈值效应,即大估计误差(异常估计)的概率迅速增加。这表明在低信噪比条件…

PULSE测量系统——示波器结合matlab

由上篇文章可知PULSE测量系统原理,以及在双传声器法传递函数中的作用。但是当没有PULSE测量系统时,我们应该用什么硬件设备与软件进行替换呢? 示波器与MATLAB的功能对比 示波器的作用: 与传声器连接,用于实时显示传声器…

Certimate自动化SSL证书部署至IIS服务器

前言:笔者上一篇内容已经部署好了Certimate开源系统,于是开始搭建部署至Linux和Windows服务器,Linux服务器十分的顺利,申请证书-部署证书很快的完成了,但是部署至Windows Server的IIS服务时,遇到一些阻碍&a…

PTA 输出三角形字符阵列

本题要求编写程序&#xff0c;输出n行由大写字母A开始构成的三角形字符阵列。 输入格式&#xff1a; 输入在一行中给出一个正整数n&#xff08;1≤n<7&#xff09;。 输出格式&#xff1a; 输出n行由大写字母A开始构成的三角形字符阵列。格式见输出样例&#xff0c;其中…

UnityShaderLab 实现黑白着色器效果

实现思路&#xff1a;取屏幕像素的RGB值&#xff0c;将三个通道的值相加&#xff0c;除以一个大于值使颜色值在0-1内&#xff0c;再乘上一个强度值调节黑白强度。 在URP中实现需要开启Opaque Texture ShaderGraph实现&#xff1a; ShaderLab实现&#xff1a; Shader "Bl…

开发者如何使用GCC提升开发效率 Windows下Cmake + NDK 交叉编译 Libyuv

最近在导入其他项目的libyuv库,编译时发现如下问题,刚好想做一期libyuv编译与安装到AS中的文章,故记录集成的全过程 报错如下 error: no member named ABGRToNV21 in namespace libyuv; did you mean ARGBToNV21? error: no member named UYVYToY in namespace libyuv; d…

EDI系统与业务系统集成:选择中间数据库还是REST API方案?

EDI项目中&#xff0c;对外企业可以借助专业的EDI系统&#xff0c;基于AS2、OFTP等国际通用的EDI传输协议搭建传输通道&#xff0c;并基于这些传输通道实现安全、可靠地数据传输。对内企业如何实现业务系统和EDI系统之间的数据同步呢&#xff1f; 企业可以通过中间数据库、RES…

ASP.NET Core实现鉴权授权的几个库

System.IdentityModel.Tokens.Jwt 和 Microsoft.AspNetCore.Authentication.JwtBearer 是两个常用的库&#xff0c;分别用于处理 JWT&#xff08;JSON Web Token&#xff09;相关的任务。它们在功能上有一定重叠&#xff0c;但侧重点和使用场景有所不同。 1. System.IdentityM…

No.4 笔记 探索网络安全:揭开Web世界的隐秘防线

在这个数字时代&#xff0c;网络安全无处不在。了解Web安全的基本知识&#xff0c;不仅能保护我们自己&#xff0c;也能帮助我们在技术上更进一步。让我们一起深入探索Web安全的世界&#xff0c;掌握那些必备的安全知识&#xff01; 1. 客户端与WEB应用安全 前端漏洞&#xff1…