对象树
Qt中的对象树机制,通俗来讲,就是当创建的对象,父窗口是QWidget或者是QObject派生下来的类,此对象就会放到父窗口的对象树上,当程序执行完毕,树上的内容会从下往上依次释放,而无需再手动释放。
这里需要注意的,释放和析构的区别,这里的析构并不代表释放。析构只是清理一下相关信息,并没有真正释放对象。因此这里析构的调用顺序和C++中的虚析构调用顺序会有些差异。
如下:
当释放最顶层Widget1窗口时,会从下往上释放。虽然从下往上释放,但也许通过上层窗口判断是否有子窗口,再执行子窗口的析构函数(这里没有释放),最后再执行释放。
比如这里释放最顶层Widget1窗口,会先执行Widget1的析构函数,执行析构并不表示释放对象,这里执行析构后会判断该窗口是否有子窗口,有子窗口Widget2, Widget3, Widget4,则会继续调用Widget2, Widget3, Widget4的析构,然后再判断是否有子窗口,还有子窗口PushButton1,则会继续释放PushButton1的析构。到这里就没有子窗口了,就开始从下面PushButton1往上层释放。
示例
这里以QWidget主窗口为例,自定义一个简单的继承至QPushButton的MyPushButton按钮类,在MyPushButton按钮类的析构中添加日志记录析构,然后销毁主窗口,查看析构顺序。
//MyPushButton.h
#ifndef MYPUSHBUTTON_H
#define MYPUSHBUTTON_H
#include <QPushButton>
class MyPushButton : public QPushButton
{
Q_OBJECT
public:
explicit MyPushButton(QWidget *parent = nullptr);
~MyPushButton();
signals:
};
#endif // MYPUSHBUTTON_H
//MuPushButton.cpp
#include "mypushbutton.h"
#include <QDebug>
MyPushButton::MyPushButton(QWidget *parent)
: QPushButton{parent}
{
}
MyPushButton::~MyPushButton()
{
qDebug() << "MyPushButton 析构函数";
}
//QWidget.cpp
#include "widget.h"
#include "mypushbutton.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
MyPushButton* myBtn = new MyPushButton(this);
myBtn->setText("我的按钮");
myBtn->move(0, 100);
}
Widget::~Widget()
{
qDebug() << "Widget 析构函数";
}
关闭QWidget主窗口,可以看到析构顺序如下:
可以看到是先调用上层窗口的析构,在调用子窗口的析构。
虽然析构顺序是从上往下,但实际的释放顺序还是从下往上的。