初识Qt:从Hello world到对象树的深度解析

Qt中的对象树深度解析

  • Hello world
    • 1.图形化界面创建
    • 命令行式创建
      • 在栈上创建
      • 在堆上创建
        • 为什么传文本需要QString,std::string不行吗?
        • 那为什么要传入this指针?为什么new后不用显示调用delete函数呢,不会造成内存泄漏问题吗?
  • 一、对象树的基本概念
  • 二、对象树的创建
    • 验证对象树的内存管理
  • 三、对象树的用途
  • 四、对象树的注意事项

Hello world

1.图形化界面创建

在这里插入图片描述
在这里插入图片描述
与上述图片中的树形结构对应,则XML代码为在这里插入图片描述

命令行式创建

在栈上创建

    //构建QLabel标签QLabel label1;label1.setText(QString("Hello World"));

这里我们采用在栈上创建Label对象,并设置其文本为Hello world,但是为什么在对话框没有显示呢?
在这里插入图片描述

局部变量:label1是一个局部变量,它在构造函数结束时会被销毁。即使您将其添加到了布局中,由于它在构造函数结束后不再存在,所以标签也不会显示出来。

在堆上创建

    //构建QLabel标签QLabel* label1=new QLabel(this);label1->setText(QString("Hello World"));

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

通过上述我们发现,现在可以显示在对话框了,但是也存在上述几个问题——

为什么传文本需要QString,std::string不行吗?

在Qt中,QString是Qt框架提供的字符串类,它与C++标准库中的std::string有所不同。尽管在某些情况下,你可以使用std::string,但在Qt应用程序中,通常建议使用QString,因为它具有以下优势:

  1. 跨平台性:QString是Qt框架的一部分,而且是跨平台的。这意味着你可以在不同的操作系统上(如Windows、Linux、macOS等)使用相同的代码,并且QString的行为将是一致的。相比之下,std::string是C++标准库的一部分,可能在不同的编译器或操作系统上有不同的实现和行为。

  2. Unicode支持:QString天生支持Unicode字符集,这意味着它可以轻松处理各种语言和特殊字符,而不会出现乱码或截断等问题。与之相比,std::string在处理Unicode字符时可能会面临一些挑战,需要谨慎处理。

  3. 方便的API:QString提供了丰富的API,可以方便地进行字符串操作,如拼接、查找、替换、大小写转换等。此外,QString还支持使用arg()方法进行字符串格式化,使得字符串处理更加灵活和便捷。

  4. 与Qt框架的集成:QString与Qt框架的其他部分无缝集成,如信号槽机制、国际化支持等。使用QString可以更容易地与其他Qt类进行交互,并且可以利用Qt提供的丰富功能来进行字符串处理。

所以,尽管string也可以作为参数传入,但是为了防止出现乱码(编码不一致)的问题,还是老实用QString传入较好(不用显示写入,通过构造函数,上述 label1->setText("Hello World");也是可以的)

那为什么要传入this指针?为什么new后不用显示调用delete函数呢,不会造成内存泄漏问题吗?

在Qt中,使用this作为父对象参数来创建对象,是为了将新创建的对象添加到当前对象的子对象列表中,并且在当前对象销毁时,这些子对象也会被自动销毁。在示例代码中,通过new QLabel(this)语句创建了一个QLabel对象,并将当前Widget对象作为其父对象

现在来解释一下为什么要传递this:

  1. 对象树管理:Qt中的对象树是通过父子关系来管理的,每个QObject都可以有一个父对象。当一个对象拥有父对象时,它就成为父对象的子对象,而且其生命周期也受父对象管理。通过将this作为父对象参数传递给new QLabel(),你告诉Qt将新创建的QLabel对象添加到当前Widget对象的子对象列表中。

  2. 内存管理:传递this作为父对象参数可以确保在当前Widget对象被销毁时,其所有子对象也会被自动销毁。这是因为Qt会自动管理父对象与其子对象之间的关系,并在父对象销毁时递归地销毁其所有子对象,从而避免内存泄漏。

因此,通过将this作为父对象参数传递给new QLabel(),可以实现对象之间的正确管理和内存自动释放。

那么肯定会疑惑,Qt真的能安全地将我们构造的对象释放吗?你怎么知道?

引入对象树

在Qt这个强大的跨平台C++图形用户界面应用程序开发框架中,对象树是一个核心概念。它不仅为Qt应用程序的内存管理提供了便利,还确保了Qt对象之间的父子关系清晰、易于理解。本文将深入解析Qt中的对象树机制,帮助读者更好地理解其在Qt应用程序中的作用。

一、对象树的基本概念

Qt中的对象树是一个树形结构,其中每个节点都是一个QObject或其派生类的实例。这些对象通过父子关系连接在一起,形成了一个层次结构。在这个结构中,每个对象都可以有一个父对象(除了根对象外),并且可以有多个子对象。
如下图所示为一颗Qt的n叉树,树的根节点为QObject
在这里插入图片描述

二、对象树的创建

在Qt中,对象的创建通常伴随着父子关系的建立。当一个QObject对象在创建时指定了一个父对象,那么这个新创建的对象就会自动添加到父对象的子对象列表中。同时,父对象会接管其所有子对象的内存管理。这意味着,当父对象被删除时,其所有子对象也会被自动删除,从而避免了内存泄漏的问题。

验证对象树的内存管理

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

tips: .h 与 .cpp之间可以通过F4快速切换

在这里插入图片描述
完成创建后编译代码,发现出现了和上述一样的结果
在这里插入图片描述
当我们关闭对话框时,则会发现其默认调用了析构函数

在这里插入图片描述

tips:调⽤析构函数和释放内存并⾮是同⼀件事情.

因此验证了对象树内存管理的机制

三、对象树的用途

  1. 内存管理:如前所述,对象树为Qt应用程序提供了自动的内存管理机制。这种机制通过父子关系来确保当一个对象不再需要时,它的所有子对象也会被正确地删除。
  2. 事件传播:在Qt中,事件(如鼠标点击、键盘输入等)是通过事件系统来传播的。当一个事件发生时,它首先被发送到接收该事件的对象。如果该对象无法处理该事件,那么事件就会沿着对象树向上传播,直到找到一个能够处理该事件的对象为止。这种机制使得Qt能够轻松地处理复杂的事件传递逻辑。
  3. 资源共享:在Qt中,一些资源(如字体、颜色等)可以在对象树中进行共享。当一个对象设置了某个资源时,它的所有子对象都可以访问和使用这个资源。这种机制减少了资源的使用量,提高了应用程序的性能。

四、对象树的注意事项

  1. 避免循环引用:循环引用是指两个或多个对象相互引用,形成一个环路。在构建对象树时,要注意避免循环引用的问题。即一个对象不能成为自己的祖先对象的子对象,否则会导致内存泄漏和其他问题。
// 错误示例:创建循环引用的对象树
QObject *parent = new QObject;
QObject *child = new QObject(parent);
parent->setParent(child); // 这里会导致循环引用// 正确示例:避免循环引用
QObject *parent = new QObject;
QObject *child = new QObject(parent); // 正确,child 是 parent 的子对象
  1. 谨慎使用setParent()方法:setParent()方法用于在运行时更改对象的父对象。但是,需要谨慎使用,因为它可能会导致一些意想不到的问题,例如事件传播错误或资源共享问题。在使用setParent()方法时,需要确保不会破坏对象之间的逻辑关系或导致不一致的状态。
// 示例:谨慎使用 setParent() 方法
QObject *parent = new QObject;
QObject *child = new QObject;// 设置 child 的父对象为 parent
child->setParent(parent);// 如果后续不再需要 parent,要特别小心
delete parent; // 这可能会导致 child 悬空指针,引发错误
  1. 注意对象的生命周期:虽然对象树提供了自动的内存管理机制,但是开发者仍然需要注意对象的生命周期。在不再需要某个对象时,最好显式地删除它(而不是仅仅断开它与父对象的连接),以确保资源的及时释放。可以通过delete操作符来显式删除对象,或者使用QObject的父子关系自动管理机制。
// 示例:注意对象的生命周期
QObject *parent = new QObject;
QObject *child = new QObject(parent);// 显式删除对象
delete parent; // 这将同时删除 parent 和 child// 或者使用父子关系自动管理
// 当 parent 被删除时,child 会自动删除

总结

Qt中的对象树是一个强大而灵活的概念,它为Qt应用程序提供了自动的内存管理、事件传播和资源共享等机制。通过深入理解对象树的工作原理和使用方法,开发者可以更加高效、安全地开发Qt应用程序。

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

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

相关文章

python:__class_getitem__使用以及cached_property源码分析

python:__class_getitem__使用以及cached_property源码分析 1 前言 Python中如何模拟泛型类型? 当使用类型标注时,使用 Python 的方括号标记来形参化一个 generic type 往往会很有用处。 例如,list[int] 这样的标注可以被用来表…

K8S集群再搭建

前述:总体是非常简单的,就是过程繁琐,不过都是些重复的操作 master成员: [controller-manager, scheduler, api-server, etcd, proxy,kubelet] node成员: [kubelet, proxy] master要修改的配置文件有 1. vi /etc/etcd/etcd.conf # 数…

wordpress教程视频 wordpress教程网盘 wordpress教程推荐wordpress教程网

WordPress,作为一款强大且灵活的开源内容管理系统,已成为许多网站开发者与运营者的首选。其强大的功能、丰富的插件以及易于上手的特点,使得无论是初学者还是专业开发者都能轻松构建出个性化的网站。然而,对于初学者来说&#xff…

JUnit5标记测试用例

使用场景: 通过Tag对用例分组: 环境分组:测试环境、预发布环境阶段分组:冒烟用例版本分组:V1.1、V1.2 Tag标记用例: 设置标签根据标签执行 结合Maven执行结合测试套件执行 设置标签: 通过T…

【Spring Cloud】全面解析服务容错中间件 Sentinel 持久化两种模式

文章目录 推送模式本地文件持久化(拉模式)配置yml编写处理类添加配置演示 配置中心持久化(推模式)修改nacos在sentinel中生效引入依赖配置文件 修改sentinel在nacos中生效下载源码更改代码演示 总结 推送模式 Sentinel 规则的推送…

allegro 无法删除Xnet

allegro 无法删除Xnet Orcad中打开Constraint Manager之后,再生成网表,导入PCB后就会出现一堆Xnet网络。无法去除Xnet。 解决办法 在原理图ORCAD中, 1、打开Edit Object properties 2、选择Filter by:Capture 3、点击New Property 4、设置…

火山引擎边缘云亮相 Force 原动力大会,探索 AI 应用新范式

5月15日,2024 春季火山引擎 FORCE 原动力大会在北京正式举办。大会聚焦 AI 主题,以大模型应用为核心、以 AI 落地为导向,展示了火山引擎在大模型、云计算领域的实践应用,携手汽车、手机终端、金融、消费、互联网等领域的专家和企业…

2024042102-array-list

数组 Array 一、前言 数组是数据结构还是数据类型? 数组只是个名称,它可以描述一组操作,也可以命名这组操作。数组的数据操作,是通过 idx->val 的方式来处理。它不是具体要求内存上要存储着连续的数据才叫数据,而…

js积累三(web页面一段时间未操作,退出登录)

//核心代码,已封装function CountDownLogout() {/* if 30 seconds no operation then logout */var maxTime 30; // seconds,可自行修改时长var time_time maxTime;/* 鼠标点击事件 */$(document).mousedown(function(){time_time maxTime; //…

EI会议的最佳论文奖是什么?如何申请?

EI会议的最佳论文奖通常是指在EI(工程索引,Engineering Index)收录的学术会议中,评选出的表现最优秀的论文奖项。以下是关于该奖项的一些基本信息及申请步骤: 最佳论文奖的含义 评选标准:最佳论文奖通常基…

多线程、进程、线程五种状态、synchronized、volatile、Lock、CAS、死锁、ThreadLocal

1、并发编程 并发编程三要素 原子性:只一个操作要么全部成功,要么全部失败可见性:一个线程对共享变量的修改,其他线程能够立刻看到有序性:程序执行的顺序按照代码的先后顺序执行 synchronized,Lock解决原…

前端vue 动态加载ts文件,动态调用ts内的方法

业务场景: 在某个业务场景中, 我们需要在数据库配置ts文件路径,和需要调用的函数名称, 前端需要再指定的场景下,触发对应的函数, 并执行处理逻辑,返回结果. 实现: 这是一个数据库配置生成的动态表单 动态校验的例子, 需要引用动态的函数校验 任意一个js文件, common1.ts c…

大模型日报|今日必读的 13 篇大模型论文

大家好,今日必读的大模型论文来啦! 1.MIT新研究:并非所有语言模型特征都是线性的 最近的研究提出了线性表征假说:语言模型通过操作激活空间中概念(“特征”)的一维表征来执行计算。与此相反,来…

CHI dataless 传输——CHI(4)

上篇介绍了read的操作类型,本篇我们来介绍一下dataless 目录 一、dataless操作概览 二、Non-CMO (Non-Cache Maintenance Operation) 1、CleanUnique 2、StashOnce and StashOnceSep 3、Evict 三、CMO (Cache Maintenance Operation) 一、dataless操作概览 名…

忍の摸头之术游戏娱乐源码

本资源提供给大家学习及参考研究借鉴美工之用,请勿用于商业和非法用途,无任何技术支持! 忍の摸头之术游戏娱乐源码,抖音上面非常火的摸头杀画面,看得我眼花缭乱,源码拿去玩吧; 目录说明 忍の摸头之术:域…

轻松同步:将照片从三星手机传输到iPad的简便方法

概括 想要在新 iPad 上查看三星照片吗?但是,如果您不知道如何将照片从三星手机传输到 iPad,则无法在 iPad 上查看图片。为此,本文分享了 7 个有用的方法,以便您可以使用它们在不同操作系统之间轻松发送照片。现在&…

EfficientSAM分割对象后求其中图像中的高

1 分割对象 EfficientSAM https://github.com/yformer/EfficientSAM 2 计算在图像中最高点即y值最小点 import os import cv2def read_images(folder_path):image_files [f for f in os.listdir(folder_path) iff.endswith(".jpg") or f.endswith(".png&quo…

虚拟化技术[1]之服务器虚拟化

文章目录 虚拟化技术简介数据中心虚拟化 服务器虚拟化服务器虚拟化层次寄居虚拟化裸机虚拟化VMM无法直接捕获特权指令解决方案 服务器虚拟化底层实现CPU虚拟化内存虚拟化I/O设备虚拟化 虚拟机迁移虚拟机动态迁移迁移内容:内存迁移迁移内容:网络资源迁移迁…

小短片创作-组装场景(一)

1、项目基础设置 通过第三人称模板,创建1个项目 1.自动曝光:关闭,因为要做专业的小短片,曝光需要手动控制。 2.扩展自动曝光中的默认亮度范围:启用 3.全局光照系统:选择屏幕空间光照(SSGI&am…

Transformer详解常见面试问题

文章目录 1. 各模块解决1.1 输入部分1.2 多头注意力(作者使用8个头)1.3 残差和LayerNorm1.4 Decoder部分 2.Transformer经典问题2.1 tranformer为何使用多头注意力机制?2.2 Transformer相比CNN的优缺点2.3 Encoder和decoder的区别&#xff1f…