1、先来看一个简单的Qt程序,代码如下:
LabelEx.h
#ifndef LABELEX_H
#define LABELEX_H
#include <qlabel.h>
// 简单重写QLabel类
class LabelEx : public QLabel
{
Q_OBJECT
public:
explicit LabelEx(QWidget *parent = nullptr);
~LabelEx();
signals:
};
#endif // LABELEX_H
LabelEx.cpp
#include "LabelEx.h"
#include <qdebug.h>
LabelEx::LabelEx(QWidget *parent)
: QLabel{parent}
{}
LabelEx::~LabelEx()
{
qDebug() << "LabelEx destructor";
}
测试对话框:
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include "LabelEx.h"
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = nullptr);
~Dialog();
private:
void init();
private:
LabelEx *m_lbInfo = nullptr;
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include <qboxlayout.h>
#include <qdebug.h>
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
init();
}
Dialog::~Dialog() {}
void Dialog::init()
{
setMinimumSize(200, 200);
m_lbInfo = new LabelEx(); // 无父对象
m_lbInfo->setText("测试1");
QHBoxLayout *hLay = new QHBoxLayout(); // 无父对象
hLay->addWidget(m_lbInfo);
if (m_lbInfo->parent() == hLay) {
qDebug() << "m_lbInfo->parent() == hLay";
}
if (m_lbInfo->parent() == this) {
qDebug() << "m_lbInfo->parent() == this";
}
if (m_lbInfo->parent() == nullptr) {
qDebug() << "m_lbInfo->parent() == nullptr";
}
if (hLay->parent() == this) {
qDebug() << "hLay->parent() == this";
}
if (hLay->parent() == nullptr) {
qDebug() << "hLay->parent() == nullptr";
}
}
运行后可以看到打印信息:
m_lbInfo->parent() == nullptr
hLay->parent() == nullptr
关闭对话框后,m_lbInfo没有调用析构函数,与hLay都存在内存泄漏的风险(因为没有父对象,不会自动释放资源)
修改Dialog::init()后:
void Dialog::init()
{
setMinimumSize(200, 200);
m_lbInfo = new LabelEx(); // 无父对象
m_lbInfo->setText("测试1");
QHBoxLayout *hLay = new QHBoxLayout(); // 无父对象
hLay->addWidget(m_lbInfo);
this->setLayout(hLay);
if (m_lbInfo->parent() == hLay) {
qDebug() << "m_lbInfo->parent() == hLay";
}
if (m_lbInfo->parent() == this) {
qDebug() << "m_lbInfo->parent() == this";
}
if (m_lbInfo->parent() == nullptr) {
qDebug() << "m_lbInfo->parent() == nullptr";
}
if (hLay->parent() == this) {
qDebug() << "hLay->parent() == this";
}
if (hLay->parent() == nullptr) {
qDebug() << "hLay->parent() == nullptr";
}
}
其实只是增加一行代码:this->setLayout(hLay)
可以看出打印信息:
m_lbInfo->parent() == this
hLay->parent() == this
由此可见,QWidget对象在调用setLayout(QLayout *lay)后,会把lay和lay布局中的QWidget对象都设为自身的子对象。
关闭对话框后,打印信息:LabelEx destructor
m_lbInfo调用了析构函数,自动释放了资源。
【题外话】QObject对象在释放资源时,会自动释放它子对象的资源,相信大家都明白,因为QObject有一个QObjectList类型的对象,专门管理子对象,包括释放自身资源前会遍历释放子对象资源。
2、扩展
修改Dialog类
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include "LabelEx.h"
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = nullptr);
~Dialog();
private:
void init();
private:
QWidget *m_wgt = nullptr;
LabelEx *m_lbInfo = nullptr;
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include <qboxlayout.h>
#include <qdebug.h>
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
init();
}
Dialog::~Dialog() {}
void Dialog::init()
{
setMinimumSize(600, 200);
m_wgt = new QWidget(); // 无父对象
m_lbInfo = new LabelEx(m_wgt); // 父对象为m_wgt
m_lbInfo->setText("测试1:");
QHBoxLayout *hLay = new QHBoxLayout();
hLay->addWidget(m_lbInfo);
m_wgt->setLayout(hLay);
QVBoxLayout *vLay = new QVBoxLayout();
vLay->addWidget(m_wgt);
this->setLayout(vLay);
if (m_lbInfo->parent() == m_wgt){
qDebug() << "m_lbInfo->parent() == m_wgt";
}
if (m_lbInfo->parent() == hLay) {
qDebug() << "m_lbInfo->parent() == hLay";
}
if (m_lbInfo->parent() == this) {
qDebug() << "m_lbInfo->parent() == this";
}
if (m_wgt->parent() == this) {
qDebug() << "m_wgt->parent() == this";
} else {
qDebug() << "m_wgt->parent() != this";
}
if (hLay->parent() == m_wgt) {
qDebug() << "hLay->parent() == m_wgt";
}
if (hLay->parent() == this) {
qDebug() << "hLay->parent() == this";
}
if (vLay->parent() == this) {
qDebug() << "vLay->parent() == this";
} else {
qDebug() << "vLay->parent() != this";
}
}
运行程序后,打印信息如下:
m_lbInfo->parent() == m_wgt
m_wgt->parent() == this
hLay->parent() == m_wgt
vLay->parent() == this
【分析】由于m_wgt嵌入在vLay布局中,而vLay的父对象是this,因而m_wgt的父对象也变为this。由于调用了m_wgt->setLayout(hLay),因而hLay的父对象是m_wgt(注意不是this),m_lbInfo嵌入在hLay中,因此它的父对象也随hLay。
退出对话框后,打印信息:LabelEx destructor
m_lbInfo自动释放了资源(它毕竟属于Dialog的孙对象,在m_wgt释放对象前不会忘了它)