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

code review!
参考笔记
1.qt-C++笔记之父类窗口、父类控件、对象树的关系
2.qt-C++笔记之继承自 QWidget和继承自QObject 并通过 getWidget() 显示窗口或控件时的区别和原理
3.qt-C++笔记之自定义类继承自 QObject 与 QWidget 及开发方式详解
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_ptr 或 std::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. 总结
- 在继承类中,通常需要在构造函数中通过调用父类的构造函数来初始化
parent。 - 合理设置
parent可以让 Qt 对象树自动管理对象的生命周期。 - 如果不使用
parent,需要手动管理对象的生命周期。 - 动态设置
parent或结合智能指针管理对象是可行的,但需要小心避免冲突。 - 在声明与实现分离时,
parent的初始化通过构造函数的初始化列表实现。 - 在头文件中声明构造函数时,可以为
parent提供默认值nullptr。 - 在源文件中通过
: QWidget(parent)调用父类构造函数进行初始化。 - 合理使用 Qt 的对象树机制,可以自动管理对象的生命周期,简化内存管理。
相关文章:
qt-C++笔记之自定义继承类初始化时涉及到parents的初始化
qt-C笔记之自定义继承类初始化时涉及到parents的初始化 code review! 参考笔记 1.qt-C笔记之父类窗口、父类控件、对象树的关系 2.qt-C笔记之继承自 QWidget和继承自QObject 并通过 getWidget() 显示窗口或控件时的区别和原理 3.qt-C笔记之自定义类继承自 QObject 与 QWidget …...
人才选拔中,如何优化面试流程
在与某大型央企的深入交流中,随着该企业的不断壮大与业务扩张,对技术人才的需求急剧上升,尽管企业加大了招聘力度并投入了大量资源,但招聘成效却不尽如人意。经过项目组细致调研与访谈,问题的根源逐渐浮出水面…...
2501wtl,皮肤技术
下载地址 设计目标 最重要的是使用方便,已有程序创建一个COM对象,调一个方法就可把界面外观全部改成Mac风格的. 另外一个目标是要有扩展性. 所以,基本设计是定义一个统一的接口,然后用不同实现.每一个实现单独放在一个COMDLL中,调用者选择一个类标创建对象就行了. 接口的定义…...
【面试题】技术场景 6、Java 生产环境 bug 排查
生产环境 bug 排查思路 分析日志:首先通过分析日志查看是否存在错误信息,利用之前讲过的 elk 及查看日志的命令缩小查找错误范围,方便定位问题。远程 debug 适用环境:一般公司正式生产环境不允许远程 debug,多在测试环…...
word论文排版常见问题汇总
word论文排版常见问题汇总 常用快捷键: Alt F9 正常模式与域代码模式切换 Ctrl F9 插入域代码 F9 刷新域代码显示,要注意选定后刷新才会有效果 word中在当前列表的基础上修改列表 在使用word时,我们会定义一个列表,并将其链接…...
传奇3仿韩服单机版安装教程+GM管理面板
今天为大家带来一款怀旧网单《传奇3仿韩服》的游戏架设,适用于单机娱乐, 仅供怀旧,本人已经安装游戏成功,特此带来详细安装教程。 适用环境 单机 视频演示 传奇3仿韩服单机 亲测截图 架设步骤 关闭默认杀毒软件和其它自己下的杀…...
第26章 汇编语言--- 内核态与用户态
汇编语言是低级编程语言的一种,它与特定计算机的硬件架构紧密相关。内核态和用户态是操作系统中进程运行的两种不同模式,它们用来区分操作系统内核代码和其他应用程序代码的执行环境。下面我将简要解释这两种状态,并给出一个简单的示例来展示…...
Spring bean的生命周期和扩展
接AnnotationConfigApplicationContext流程看实例化的beanPostProcessor-CSDN博客,以具体实例看bean生命周期的一些执行阶段 bean生命周期流程 生命周期扩展处理说明实例化:createBeanInstance 构造方法, 如Autowired的构造方法注入依赖bean 如UserSer…...
计算机网络 (33)传输控制协议TCP概述
一、定义与基本概念 TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。它工作在OSI模型的第四层,即传输层,为用户提供可靠的、有序的和无差错的数据传输服务。TCP协议与UDP协议是传输层的两大主要协议,但两者在设计上有明显的不同&…...
Python3 JSON
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它基于JavaScript编程语言的一个子集,但JSON是独立于语言的,很多编程语言都支持JSON格式数据的…...
Leetcode 698 Partition to K Equal Sum Subsets
题意 给一个数组,要求把数组里的元素分成k个子集,满足每个子集中数的总和是相等的。问是否能分成k个子集 题目链接 https://leetcode.com/problems/partition-to-k-equal-sum-subsets/description/ 思考 想象你有k个桶,然后你有n个小球&…...
可靠的人形探测,未完待续(III)
一不小心,此去经年啊。问大家新年快乐! 那,最近在研究毫米波雷达模块嘛,期望用在后续的产品中,正好看到瑞萨的活动送板子,手一下没忍住。 拿了板子就得干活咯,我一路火花带闪电,开整…...
Git文件夹提交错了,怎么撤销?
最近提交了一些不应该提交的文件夹到git中,现在需要移除它们,现在简单记录一下操作日志: 情况一 文件夹已经被添加到 Git,但未提交 如果文件夹已经被 git add 添加到暂存区中,但尚未提交,你可以使用以下命令将其从暂存区中移除: git rm -r …...
小程序textarea组件键盘弹起会遮挡住输入框
<textarea value"{{remark}}" input"handleInputRemark" ></textarea> 如下会有遮挡: 一行代码搞定 cursor-spacing160 修改后代码 <textarea value"{{remark}}" input"handleInputRemark" cursor-spacin…...
Android车机DIY开发之学习篇(二)编译Kernel以正点原子为例
Android车机DIY开发之学习篇(二)编译Kernel以正点原子为例 1.代码在/kernel-5.10文件夹下 2.在kernel-5.10目录下执行如下命令编译 : 编译之前,需要将 clang 导出到 PATH 环境变量: 如果是 Android12 执行下面这条命令 export PATH../pr…...
qt 窗口(window/widget)绘制/渲染顺序 QPainter QPaintDevice Qpainter渲染 失效 无效
qt窗体布局 窗体渲染过程 qt中窗体渲染逻辑顺序为 本窗体->子窗体/控件 递归,也就是说先渲染父窗体再渲染子窗体。其中子窗体按加入时的先后顺序进行渲染。通过下方的函数调用堆栈可以看出窗体都是在widget组件源码的widgetprivate::drawwidget中进行渲染的&am…...
Ubuntu下载时不显示无线网图标并显示Cable unplugged
我用的是ubuntu22-04-5.iso一下载出来发现无法连接网络甚至直接显示Wired是Cable unplugged. 下面是解决方法: step1: step2:点击编辑中的虚拟网络编辑器 step3: step4: step5: step6:取消勾选自动检测可用的DNS服务器 step7:在window上按下winR输入c…...
微信小程序实现人脸识别登录
hello hello~ ,这里是 code袁~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 🦁作者简介:一名喜欢分享和记录学习的在校大学生…...
atoi函数的概念和使用案例
atoi 函数是 C 语言标准库中的一个函数,它用于将字符串转换为整数。atoi 的名称是 “ASCII to integer” 的缩写。该函数定义在 <stdlib.h> 头文件中。 概念 atoi 函数会从字符串的开始位置开始转换,直到遇到第一个非数字字符或遇到字符串结束符…...
Mysql--运维篇--日志管理(连接层,SQL层,存储引擎层,文件存储层)
MySQL提供了多种日志类型,用于记录不同的活动和事件。这些日志对于数据库的管理、故障排除、性能优化和安全审计非常重要。 一、错误日志 (Error Log) 作用: 记录MySQL服务器启动、运行和停止期间遇到的问题和错误信息。 查看: 默认情况下…...
华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
Unity VR/MR开发-VR开发与传统3D开发的差异
视频讲解链接:【XR马斯维】VR/MR开发与传统3D开发的差异【UnityVR/MR开发教程--入门】_哔哩哔哩_bilibili...
客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践
01技术背景与业务挑战 某短视频点播企业深耕国内用户市场,但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大,传统架构已较难满足当前企业发展的需求,企业面临着三重挑战: ① 业务:国内用户访问海外服…...
Redis上篇--知识点总结
Redis上篇–解析 本文大部分知识整理自网上,在正文结束后都会附上参考地址。如果想要深入或者详细学习可以通过文末链接跳转学习。 1. 基本介绍 Redis 是一个开源的、高性能的 内存键值数据库,Redis 的键值对中的 key 就是字符串对象,而 val…...
【threejs】每天一个小案例讲解:创建基本的3D场景
代码仓 GitHub - TiffanyHoo/three_practices: Learning three.js together! 可自行clone,无需安装依赖,直接liver-server运行/直接打开chapter01中的html文件 运行效果图 知识要点 核心三要素 场景(Scene) 使用 THREE.Scene(…...
