说明qt对象树 对象析构顺序为:
- 本对象的析构函数
- 栈成员
- 对象树中自己的孩子们
- 对象树中自己的孙子们
所以,千万别在孩子对象中(qt对象树特有的这个连带析构关系)去访问父对象的任何栈成员(包括堆成员)的信息了(其实压根父对象自己都别访问了,因为父对象本身就已经先析构了),因为目标内存已经释放了,所以可能导致隐形的崩溃,问题是比较难查的了。
如果非要在子子对象析构函数里访问父对象信息,当父对象仍然存在时是没有问题的(例如Tabwidget包含多个tab页面,手动一个一个先叉掉这些页面,也就是先析构它们,这样就能保证父对象一直存在,即安全的),但是如果是直接叉掉Tabwidget,希望自动析构多个子tab页面,此时就不能在子对象析构函数里访问父对象信息的操作了,如果非要这样干,那就在父对象Tabwidget的析构函数里先一个个子对象的delete吧,这样也是安全了,就是多写几行代码了。
还有个方法也安全:子对象里用发射信号的方式,让父对象执行目标操作,这样为什么安全呢,因为父对象如果已经被析构了,大不了这个槽函数不执行,也不会崩溃的,此外父对象都不存在了,说明是所有对象进行连带析构了,说明软件要关闭了,这个父对象槽函数不执行也无所谓了。
本实验源码:
类A
#ifndef A_H
#define A_H
#include <QObject>
class B;
class A : public QObject
{
Q_OBJECT
public:
explicit A(QObject *parent = nullptr);
~A();
B* parentB = nullptr;
signals:
};
#endif // A_H
#include "a.h"
#include "b.h"
#include <QDebug>
A::A(QObject *parent)
: QObject{parent}
{
parentB = (B*)parent;
}
A::~A()
{
parentB->getA2()->fun("now do getA2()->fun");
qDebug()<<"~A";
}
类A2
#ifndef A2_H
#define A2_H
#include <QObject>
class A2 : public QObject
{
Q_OBJECT
public:
explicit A2(QObject *parent = nullptr);
~A2();
void fun(QString str);
signals:
};
#endif // A2_H
#include "a2.h"
#include <QDebug>
A2::A2(QObject *parent)
: QObject{parent}
{}
A2::~A2()
{
qDebug()<<"~A2";
}
void A2::fun(QString str)
{
qDebug()<<"A2::fun called "<<str;
}
类B
#ifndef B_H
#define B_H
#include <QObject>
#include "a.h"
#include "a2.h"
class B : public QObject
{
Q_OBJECT
public:
explicit B(QObject *parent = nullptr);
~B();
A2* getA2(){return &a2;}
signals:
private:
A2 a2;
A* a = nullptr;
A* aa = nullptr;
};
#endif // B_H
#include "b.h"
#include <QDebug>
B::B(QObject *parent)
: QObject{parent}
{
a = new A(this);
aa = new A(this);
}
B::~B()
{
qDebug()<<"~B";
}
类Mainwindow
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "a.h"
class B;
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
B* b;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "b.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
b = new B();
}
MainWindow::~MainWindow()
{
qDebug()<<"~MainWindow";
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
qDebug()<<"do delete b";
delete b;
}
其它可供参考博客:
Qt学习记录(4)——对象树_qt的对象树-CSDN博客