当前位置: 首页 > news >正文

qt-C++笔记之自定义继承类初始化时涉及到parents的初始化

qt-C++笔记之自定义继承类初始化时涉及到parents的初始化

在这里插入图片描述

code review!

参考笔记
1.qt-C++笔记之父类窗口、父类控件、对象树的关系
2.qt-C++笔记之继承自 QWidget和继承自QObject 并通过 getWidget() 显示窗口或控件时的区别和原理
3.qt-C++笔记之自定义类继承自 QObjectQWidget 及开发方式详解
4.qt-C++笔记之自定义继承类初始化时涉及到parents的初始化

文章目录

  • qt-C++笔记之自定义继承类初始化时涉及到parents的初始化
    • 一.声明和实现在一起
      • 1. 构造函数中传递 `parent`
      • 2. 父类 `parent` 的作用
      • 3. 子类中未显式初始化父类 `parent` 的情况
      • 4. 动态设置父对象
      • 5. 使用智能指针管理对象
      • 6. 完整示例
    • 二.声明和实现分开
      • 1. 头文件(声明部分)
      • 2. 源文件(实现部分)
      • 3. 完整示例
        • 头文件(`MyWidget.h`)
        • 源文件(`MyWidget.cpp`)
        • 主程序(`main.cpp`)
      • 4. 关键点解析
        • 1. 头文件中声明构造函数
        • 2. 源文件中通过初始化列表传递 `parent`
        • 3. 使用 Qt 的对象树
        • 4. 在构造函数中初始化子对象
      • 5. 运行效果
      • 6. 总结

在 Qt 的 C++ 开发中,当我们创建一个类继承自 Qt 的某个类(比如 QObject 或者 QWidget)时,通常需要在构造函数中对父类的 parent 指针进行初始化。这是 Qt 的对象树管理机制的核心部分之一。

Qt 中的对象树通过 parent 指针来自动管理对象的生命周期。当一个父对象被销毁时,它会自动销毁所有的子对象。因此,合理地设置 parent 是很重要的。

以下是如何在继承类中初始化父类的 parent 的一些说明和示例:

一.声明和实现在一起

1. 构造函数中传递 parent

当定义自己的继承类时,可以在构造函数中接受一个 parent 参数,并将其传递给父类的构造函数。

#include <QWidget>class MyWidget : public QWidget {
public:explicit MyWidget(QWidget *parent = nullptr) : QWidget(parent)  // 调用父类的构造函数,初始化 parent{// 其他初始化代码}
};

在上面的代码中:

  • MyWidget 是从 QWidget 继承的。
  • 构造函数接受一个 QWidget *parent 参数,并将其传递给 QWidget 的构造函数来初始化父类的 parent

2. 父类 parent 的作用

parent 参数的作用是将当前对象附加到指定的父对象上,从而形成一个 Qt 对象树。例如:

QWidget *mainWindow = new QWidget;
MyWidget *childWidget = new MyWidget(mainWindow);  // 设置 mainWindow 为 parent

在这种情况下:

  • mainWindow 是父对象。
  • childWidget 被添加为 mainWindow 的子对象。
  • mainWindow 被销毁时,childWidget 会被自动销毁。

3. 子类中未显式初始化父类 parent 的情况

如果子类没有显式初始化父类的 parent 参数,默认情况下,Qt 对象的父类指针会被设置为 nullptr

class MyWidget : public QWidget {
public:MyWidget() {// 未显式传递 parent,parent 默认为 nullptr}
};

这意味着:

  • 对象不会自动附加到任何父对象。
  • 必须手动管理该对象的生命周期。

4. 动态设置父对象

即使在构造函数中没有传递 parent,也可以通过调用 setParent 方法在运行时动态设置父对象:

MyWidget *childWidget = new MyWidget;
childWidget->setParent(mainWindow);  // 动态设置 parent

这种方法在需要在对象创建后再决定其父对象时非常有用。

5. 使用智能指针管理对象

如果你不想依赖 Qt 的对象树,也可以使用标准的 C++ 智能指针(如 std::unique_ptrstd::shared_ptr)来管理对象的生命周期。但是,如果使用智能指针,就不要设置 parent,以免 Qt 和智能指针同时试图管理对象的生命周期,导致潜在的问题。

6. 完整示例

以下是一个完整的例子,展示如何正确初始化和使用 parent

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>class MyWidget : public QWidget {
public:explicit MyWidget(QWidget *parent = nullptr): QWidget(parent)  // 初始化父类的 parent{QVBoxLayout *layout = new QVBoxLayout(this);QPushButton *button = new QPushButton("Click Me", this);layout->addWidget(button);setLayout(layout);}
};int main(int argc, char *argv[]) {QApplication app(argc, argv);QWidget *mainWindow = new QWidget;MyWidget *childWidget = new MyWidget(mainWindow);mainWindow->resize(400, 300);mainWindow->show();return app.exec();
}

在这个例子中:

  • MyWidget 是一个自定义的 QWidget 子类。
  • MyWidget 的父对象是 mainWindow
  • mainWindow 被销毁时,MyWidget 也会被自动销毁。

二.声明和实现分开

当我们在 C++ 中将继承类的声明和实现分离时,涉及到 Qt 的 parent 初始化时,依然需要通过构造函数初始化列表在实现文件中将 parent 参数传递给父类的构造函数。以下是详细的分离步骤和示例。

1. 头文件(声明部分)

在头文件中声明类及构造函数,通常会为 parent 参数提供一个默认值(通常为 nullptr),这样在使用时可以选择是否显式传递父对象。

#ifndef MYWIDGET_H
#define MYWIDGET_H#include <QWidget>class MyWidget : public QWidget {Q_OBJECT  // 如果使用信号和槽机制,必须添加 Q_OBJECT 宏public:// 构造函数声明,带 parent 参数,默认值为 nullptrexplicit MyWidget(QWidget *parent = nullptr);// 其他成员函数声明(如果有)
};#endif // MYWIDGET_H

2. 源文件(实现部分)

在源文件中实现构造函数时,使用初始化列表将 parent 参数传递给父类的构造函数。

#include "MyWidget.h"// 构造函数实现
MyWidget::MyWidget(QWidget *parent): QWidget(parent)  // 将 parent 传递给 QWidget 的构造函数
{// 在这里编写其他初始化代码
}

3. 完整示例

以下是一个完整的例子,展示了如何分离声明和实现,同时正确初始化 parent

头文件(MyWidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>class MyWidget : public QWidget {Q_OBJECTpublic:explicit MyWidget(QWidget *parent = nullptr);  // 构造函数声明private:QVBoxLayout *layout;  // 布局管理器QPushButton *button;  // 按钮
};#endif // MYWIDGET_H
源文件(MyWidget.cpp
#include "MyWidget.h"// 构造函数实现
MyWidget::MyWidget(QWidget *parent): QWidget(parent)  // 将 parent 传递给父类 QWidget 的构造函数
{// 初始化布局和按钮layout = new QVBoxLayout(this);  // 将布局设置为当前 MyWidget 的子对象button = new QPushButton("Click Me", this);  // 将按钮设置为当前 MyWidget 的子对象layout->addWidget(button);  // 将按钮添加到布局中setLayout(layout);          // 应用布局到当前 widget
}
主程序(main.cpp
#include <QApplication>
#include "MyWidget.h"int main(int argc, char *argv[]) {QApplication app(argc, argv);QWidget *mainWindow = new QWidget;  // 创建主窗口MyWidget *childWidget = new MyWidget(mainWindow);  // 将 mainWindow 作为 parentmainWindow->resize(400, 300);mainWindow->show();  // 显示主窗口return app.exec();
}

4. 关键点解析

1. 头文件中声明构造函数

explicit MyWidget(QWidget *parent = nullptr);

  • 使用 explicit 关键字可以防止隐式类型转换。
  • parent 参数的默认值为 nullptr,这样在不需要父对象时可以直接创建孤立的对象。
2. 源文件中通过初始化列表传递 parent

MyWidget::MyWidget(QWidget *parent) : QWidget(parent)

  • QWidget(parent) 是父类构造函数的调用,它会将 parent 初始化为当前对象的父对象。
  • 这是遵循 C++ 的构造函数初始化列表的标准写法。
3. 使用 Qt 的对象树

通过传递 parent,可以让 MyWidget 成为其父对象的一部分,Qt 的对象树将自动管理子对象的生命周期。例如:

  • 如果 MyWidget 的父对象是 mainWindow,销毁 mainWindow 会自动销毁其所有子对象,包括 MyWidget
4. 在构造函数中初始化子对象

MyWidget 的构造函数中,布局和按钮都通过 new 创建,并将当前对象(this)作为它们的父对象:

layout = new QVBoxLayout(this);  // 布局的父对象是 MyWidget
button = new QPushButton("Click Me", this);  // 按钮的父对象是 MyWidget

这确保了这些子对象会被 MyWidget 自动管理,无需手动释放。

5. 运行效果

运行上述程序后:

  • mainWindow 是主窗口。
  • MyWidget 是主窗口的子对象。
  • 当你关闭 mainWindow 时,MyWidget 会被自动销毁。
  • 按钮和布局也会被自动销毁,因为它们是 MyWidget 的子对象。

6. 总结

  1. 在继承类中,通常需要在构造函数中通过调用父类的构造函数来初始化 parent
  2. 合理设置 parent 可以让 Qt 对象树自动管理对象的生命周期。
  3. 如果不使用 parent,需要手动管理对象的生命周期。
  4. 动态设置 parent 或结合智能指针管理对象是可行的,但需要小心避免冲突。
  5. 在声明与实现分离时,parent 的初始化通过构造函数的初始化列表实现。
  6. 在头文件中声明构造函数时,可以为 parent 提供默认值 nullptr
  7. 在源文件中通过 : QWidget(parent) 调用父类构造函数进行初始化。
  8. 合理使用 Qt 的对象树机制,可以自动管理对象的生命周期,简化内存管理。

相关文章:

qt-C++笔记之自定义继承类初始化时涉及到parents的初始化

qt-C笔记之自定义继承类初始化时涉及到parents的初始化 code review! 参考笔记 1.qt-C笔记之父类窗口、父类控件、对象树的关系 2.qt-C笔记之继承自 QWidget和继承自QObject 并通过 getWidget() 显示窗口或控件时的区别和原理 3.qt-C笔记之自定义类继承自 QObject 与 QWidget …...

人才选拔中,如何优化面试流程

在与某大型央企的深入交流中&#xff0c;随着该企业的不断壮大与业务扩张&#xff0c;对技术人才的需求急剧上升&#xff0c;尽管企业加大了招聘力度并投入了大量资源&#xff0c;但招聘成效却不尽如人意。经过项目组细致调研与访谈&#xff0c;问题的根源逐渐浮出水面&#xf…...

2501wtl,皮肤技术

下载地址 设计目标 最重要的是使用方便,已有程序创建一个COM对象,调一个方法就可把界面外观全部改成Mac风格的. 另外一个目标是要有扩展性. 所以,基本设计是定义一个统一的接口,然后用不同实现.每一个实现单独放在一个COMDLL中,调用者选择一个类标创建对象就行了. 接口的定义…...

【面试题】技术场景 6、Java 生产环境 bug 排查

生产环境 bug 排查思路 分析日志&#xff1a;首先通过分析日志查看是否存在错误信息&#xff0c;利用之前讲过的 elk 及查看日志的命令缩小查找错误范围&#xff0c;方便定位问题。远程 debug 适用环境&#xff1a;一般公司正式生产环境不允许远程 debug&#xff0c;多在测试环…...

word论文排版常见问题汇总

word论文排版常见问题汇总 常用快捷键&#xff1a; Alt F9 正常模式与域代码模式切换 Ctrl F9 插入域代码 F9 刷新域代码显示&#xff0c;要注意选定后刷新才会有效果 word中在当前列表的基础上修改列表 在使用word时&#xff0c;我们会定义一个列表&#xff0c;并将其链接…...

传奇3仿韩服单机版安装教程+GM管理面板

今天为大家带来一款怀旧网单《传奇3仿韩服》的游戏架设&#xff0c;适用于单机娱乐&#xff0c; 仅供怀旧&#xff0c;本人已经安装游戏成功&#xff0c;特此带来详细安装教程。 适用环境 单机 视频演示 传奇3仿韩服单机 亲测截图 架设步骤 关闭默认杀毒软件和其它自己下的杀…...

第26章 汇编语言--- 内核态与用户态

汇编语言是低级编程语言的一种&#xff0c;它与特定计算机的硬件架构紧密相关。内核态和用户态是操作系统中进程运行的两种不同模式&#xff0c;它们用来区分操作系统内核代码和其他应用程序代码的执行环境。下面我将简要解释这两种状态&#xff0c;并给出一个简单的示例来展示…...

Spring bean的生命周期和扩展

接AnnotationConfigApplicationContext流程看实例化的beanPostProcessor-CSDN博客&#xff0c;以具体实例看bean生命周期的一些执行阶段 bean生命周期流程 生命周期扩展处理说明实例化:createBeanInstance 构造方法&#xff0c; 如Autowired的构造方法注入依赖bean 如UserSer…...

计算机网络 (33)传输控制协议TCP概述

一、定义与基本概念 TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。它工作在OSI模型的第四层&#xff0c;即传输层&#xff0c;为用户提供可靠的、有序的和无差错的数据传输服务。TCP协议与UDP协议是传输层的两大主要协议&#xff0c;但两者在设计上有明显的不同&…...

Python3 JSON

JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;易于人阅读和编写&#xff0c;同时也易于机器解析和生成。它基于JavaScript编程语言的一个子集&#xff0c;但JSON是独立于语言的&#xff0c;很多编程语言都支持JSON格式数据的…...

Leetcode 698 Partition to K Equal Sum Subsets

题意 给一个数组&#xff0c;要求把数组里的元素分成k个子集&#xff0c;满足每个子集中数的总和是相等的。问是否能分成k个子集 题目链接 https://leetcode.com/problems/partition-to-k-equal-sum-subsets/description/ 思考 想象你有k个桶&#xff0c;然后你有n个小球&…...

可靠的人形探测,未完待续(III)

一不小心&#xff0c;此去经年啊。问大家新年快乐&#xff01; 那&#xff0c;最近在研究毫米波雷达模块嘛&#xff0c;期望用在后续的产品中&#xff0c;正好看到瑞萨的活动送板子&#xff0c;手一下没忍住。 拿了板子就得干活咯&#xff0c;我一路火花带闪电&#xff0c;开整…...

Git文件夹提交错了,怎么撤销?

最近提交了一些不应该提交的文件夹到git中,现在需要移除它们,现在简单记录一下操作日志: 情况一 文件夹已经被添加到 Git&#xff0c;但未提交 如果文件夹已经被 git add 添加到暂存区中&#xff0c;但尚未提交&#xff0c;你可以使用以下命令将其从暂存区中移除: git rm -r …...

小程序textarea组件键盘弹起会遮挡住输入框

<textarea value"{{remark}}" input"handleInputRemark" ></textarea> 如下会有遮挡&#xff1a; 一行代码搞定 cursor-spacing160 修改后代码 <textarea value"{{remark}}" input"handleInputRemark" cursor-spacin…...

Android车机DIY开发之学习篇(二)编译Kernel以正点原子为例

Android车机DIY开发之学习篇(二)编译Kernel以正点原子为例 1.代码在/kernel-5.10文件夹下 2.在kernel-5.10目录下执行如下命令编译 &#xff1a; 编译之前&#xff0c;需要将 clang 导出到 PATH 环境变量&#xff1a; 如果是 Android12 执行下面这条命令 export PATH../pr…...

qt 窗口(window/widget)绘制/渲染顺序 QPainter QPaintDevice Qpainter渲染 失效 无效

qt窗体布局 窗体渲染过程 qt中窗体渲染逻辑顺序为 本窗体->子窗体/控件 递归&#xff0c;也就是说先渲染父窗体再渲染子窗体。其中子窗体按加入时的先后顺序进行渲染。通过下方的函数调用堆栈可以看出窗体都是在widget组件源码的widgetprivate::drawwidget中进行渲染的&am…...

Ubuntu下载时不显示无线网图标并显示Cable unplugged

我用的是ubuntu22-04-5.iso一下载出来发现无法连接网络甚至直接显示Wired是Cable unplugged. 下面是解决方法&#xff1a; step1: step2:点击编辑中的虚拟网络编辑器 step3: step4: step5: step6:取消勾选自动检测可用的DNS服务器 step7&#xff1a;在window上按下winR输入c…...

微信小程序实现人脸识别登录

hello hello~ &#xff0c;这里是 code袁~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生…...

atoi函数的概念和使用案例

atoi 函数是 C 语言标准库中的一个函数&#xff0c;它用于将字符串转换为整数。atoi 的名称是 “ASCII to integer” 的缩写。该函数定义在 <stdlib.h> 头文件中。 概念 atoi 函数会从字符串的开始位置开始转换&#xff0c;直到遇到第一个非数字字符或遇到字符串结束符…...

Mysql--运维篇--日志管理(连接层,SQL层,存储引擎层,文件存储层)

MySQL提供了多种日志类型&#xff0c;用于记录不同的活动和事件。这些日志对于数据库的管理、故障排除、性能优化和安全审计非常重要。 一、错误日志 (Error Log) 作用&#xff1a; 记录MySQL服务器启动、运行和停止期间遇到的问题和错误信息。 查看&#xff1a; 默认情况下…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端&#xff0c;它允许HTTP与Elasticsearch 集群通信&#xff0c;而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

NPOI操作EXCEL文件 ——CAD C# 二次开发

缺点:dll.版本容易加载错误。CAD加载插件时&#xff0c;没有加载所有类库。插件运行过程中用到某个类库&#xff0c;会从CAD的安装目录找&#xff0c;找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库&#xff0c;就用插件程序加载进…...