Qt对象间的父子关系

1 Qt对象间的父子关系

1.1 Qt对象间的父子关系概述

Qt对象间可以存在父子关系:

  • 每一个对象都保存有它所有子对象的指针。
  • 每一个对象都有一个指向其父对象的指针。
    在这里插入图片描述
    当指定Qt对象的父对象时:
  • 其父对象会在子对象链表中加入该对象的指针。
  • 该对象会保存指向其父对象的指针。
    在这里插入图片描述
    编程实验:对象间的父子关系
void fcTest()
{
    QObject* p = new QObject();
    QObject* c1 = new QObject();
    QObject* c2 = new QObject();

    c1->setParent(p);
    c2->setParent(p);

    qDebug() << "c1: " << c1;
    qDebug() << "c2: " << c2;

    const QObjectList& list = p->children();

    for(int i=0; i<list.length(); i++)
    {
        qDebug() << list[i];
    }

    qDebug() << "p: " << p;

    qDebug() << "c1 parent: " << c1->parent();
    qDebug() << "c2 parent: " << c2->parent();
}

当Qt对象被销毁时:

  • 将自己从父对象的Children List移除。
  • 将自己的Children中的所有对象销毁。

使用Qt开发时,不仅要时刻注意内存泄漏的问题,还要实际可关注对象是否可能被多次销毁的问题!

Qt中对象树的概念:

  • 利用Qt对象间的父子关系可以构成对象树。
  • 删除树中的节点时会导致对应的子树被销毁。

在这里插入图片描述
编程实验:对象的删除

#include <QtCore/QCoreApplication>
#include <QDebug>

class MObj : public QObject
{
    QString m_name;
public:
    MObj(const QString& name)
    {
        m_name = name;

        qDebug() << "Constructor: " << m_name;
    }

    ~MObj()
    {
        qDebug() << "Destructor: " << m_name;
    }
};


void delTest()
{
    MObj* obj1 = new MObj("obj1");
    MObj* obj2 = new MObj("obj2");
    MObj* obj3 = new MObj("obj3");
    MObj* obj4 = new MObj("obj4");

    obj2->setParent(obj1);
    obj3->setParent(obj1);
    obj4->setParent(obj3);

    delete obj3;

    const QObjectList& list = obj1->children();

    qDebug() << "obj2: " << obj2;

    for(int i=0; i<list.length(); i++)
    {
        qDebug() << list[i];
    }

}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    delTest();
    
    return a.exec();
}

1.2 关于Qt对象间的父子关系的疑问

代码如下:

#include <QtCore/QCoreApplication>
#include <QDebug>
#include <QString>

class Test : public QObject
{
private:
    QString m_name;

public:
    Test(QString name, QObject* parent)
    {
        m_name = name;
        qDebug() << "construct : " << m_name;
        setParent(parent);
    }

    ~Test()
    {
        qDebug() << "deconstruct : " << m_name;
    }
};


class App : public QObject
{
private:
    Test t1;
    Test t2;
    Test* pt3;
public:
    App() : t1("t1", this), t2("t2", this)
    {

        qDebug() << "construct : App";
        pt3 = new Test("pt3", this);
    }

    ~App()
    {
        qDebug() << "deconstruct : App";
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    
    App* app = new App;

    /*
     * 这里*app和其成员变量t1、t2之间是父子关系,按理说我delete app指针的时候,会将其所有的子对象进行销毁(这应该调用t1和t2的析构函数),
     * 然后按照析构函数的调用顺序,会调用t1和t2的析构顺序。这样的话t1和t2的析构函数就会调用两次。而实际上只调用了一次,这是为什么呢?
     * 输出结果如下:
     *  construct :  "t1"
        construct :  "t2"
        construct : App
        deconstruct : App
        deconstruct :  "t2"
        deconstruct :  "t1"
        deconstruct :  "pt3"
        从上面的输出结果可以看出t2、t1是自己释放的,而不是由父对象释放的,这是为什么呢?

	  哎,自己被自己误导,上面的输出结果是正确的:会先调用App本身的析构函数,然后再调用成员变量的析构函数(调用成员变量的析构函数时就会将自己从父对象的children列表中删除),最后调用父对象的析构函数,在最底层的QObject析构函数中才会去对children列表中的对象进行删除。
     */

    delete app;

    return a.exec();
}

输出结果为:
在这里插入图片描述


参考资料:

  1. QT实验分析教程
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值