网站维护升级页面,网站建设必须买主机吗,wordpress米课,建立网站一般多少钱qt-C笔记之自定义继承类初始化时涉及到parents的初始化 code review!
参考笔记 1.qt-C笔记之父类窗口、父类控件、对象树的关系 2.qt-C笔记之继承自 QWidget和继承自QObject 并通过 getWidget() 显示窗口或控件时的区别和原理 3.qt-C笔记之自定义类继承自 QObject 与 QWidget …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. 构造函数中传递 parent2. 父类 parent 的作用3. 子类中未显式初始化父类 parent 的情况4. 动态设置父对象5. 使用智能指针管理对象6. 完整示例 二.声明和实现分开1. 头文件声明部分2. 源文件实现部分3. 完整示例头文件MyWidget.h源文件MyWidget.cpp主程序main.cpp 4. 关键点解析1. 头文件中声明构造函数2. 源文件中通过初始化列表传递 parent3. 使用 Qt 的对象树4. 在构造函数中初始化子对象 5. 运行效果6. 总结 在 Qt 的 C 开发中当我们创建一个类继承自 Qt 的某个类比如
QObject 或者
QWidget时通常需要在构造函数中对父类的
parent 指针进行初始化。这是 Qt 的对象树管理机制的核心部分之一。 Qt 中的对象树通过 parent 指针来自动管理对象的生命周期。当一个父对象被销毁时它会自动销毁所有的子对象。因此合理地设置 parent 是很重要的。
以下是如何在继承类中初始化父类的 parent 的一些说明和示例
一.声明和实现在一起
1. 构造函数中传递 parent
当定义自己的继承类时可以在构造函数中接受一个 parent 参数并将其传递给父类的构造函数。
#include QWidgetclass 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() {// 未显式传递 parentparent 默认为 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 QVBoxLayoutclass 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 QWidgetclass MyWidget : public QWidget {Q_OBJECT // 如果使用信号和槽机制必须添加 Q_OBJECT 宏public:// 构造函数声明带 parent 参数默认值为 nullptrexplicit MyWidget(QWidget *parent nullptr);// 其他成员函数声明如果有
};#endif // MYWIDGET_H2. 源文件实现部分
在源文件中实现构造函数时使用初始化列表将 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 QVBoxLayoutclass 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.hint 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 的对象树机制可以自动管理对象的生命周期简化内存管理。