Qt中的对象树

一. QT对象树的概念

QObject 的构造函数中会传入一个 Parent 父对象指针,children() 函数返回 QObjectList。即每一个 QObject 对象有且仅有一个父对象,但可以有很多个子对象。

那么Qt这样设计的好处是什么呢?很简单,就是为了方便内存管理。在创建QObject对象时,可以提供一个父对象,我们创建的这个QObject对象会自动添加到其父对象的children()列表,当父对象析构的时候,这个列表的所有对象也会被析构。当析构子对象的时候,会自动从父对象的子对象列表中删除。

当一个Q0bject对象在堆上创建的时候,Qt会同时为其创建一个对象树。不过,对象树中对象的顺序是没有定义的。这意味着,销毁这些对象的顺序也是未定义的。任何对象树中的Q0bject对象delete的时候,如果这个对象有 parent,则自动将其从parent的children()列表中删除;如果有孩子,则自动delete 每一个孩子。Qt 保证没有 Q0bject 会被 delete 两次,这是由析构顺序决定的。

如果 Q0bject 在栈上创建,Qt 保持同样的行为。正常情况下,这也不会发生什么问题。来看下下面的代码片段:

复制代码
{
    QWidget window;
    QPushButton quit("Quit",&window);
}

作为父组件的 window 和作为子组件的 quit 都是 Q0bject 的子类(事实上,它们都是 QWidget 的子类,而 QWidget是Q0bject 的子类)。这段代码是正确的,quit 的析构函数不会被调用两次,因为标准 C++要求,局部对象的析构顺序应该按照其创建顺序的相反过程。因此,这段代码在超出作用域时,会先调用 quit的析构函数,将其从父对象window的子对象列表中删除,然后才会再调用window 的析构函数。

二. 使用纯C++实现QT对象树内存回收机制底层原理

复制代码
#include <iostream>
#include <list>
using namespace std;
class Object;
typedef list<Object*> ObjectList;

class Object
{
public:
    ObjectList children_List;
    Object(Object* parent = nullptr)
    {
        if(parent != nullptr)
        {
            parent->children_List.push_back(this);
        }
    }
    //为了保证使用多态时,子类对象无法释放的问题,所以加一个virtual
    virtual ~Object()
    {
        for(auto it = children_List.begin(); it != children_List.end(); it++)
        {
            delete *(it);
        }
    }
};

class A : public Object
{
public:
    A(Object* parent = nullptr)
    {
        if(parent != nullptr)
        {
            parent->children_List.push_back(this);
        }
        cout<<"A gouzao"<<endl;
    }
    ~A()
    {
       cout<<"A xigou"<<endl;
    }
};

class B : public Object
{
public:
    B(Object* parent = nullptr)
    {
        if(parent != nullptr)
        {
            parent->children_List.push_back(this);
        }
        cout<<"B gouzao"<<endl;
    }
    ~B()
    {
       cout<<"B xigou"<<endl;
    }
};

int main()
{
//    Object obj;
//    A* a = new A(&obj);
    B b;
    A* a = new A(&b);//new A是一个继承的子类对象 b父类的指针 也就是b的孩子列表中装入了A这个对象 B和A不是继承关系,
   //不需要指针,也不需要delete,内存就能被完整的释放掉
    return 0;
}

virtual 为了保证使用多态时,子类对象无法释放的问题,所以加一个virtual

auto 是自动类型判断

相关推荐
祁同伟.43 分钟前
【C++】多态
开发语言·c++
rechol43 分钟前
C++ 继承笔记
java·c++·笔记
朱嘉鼎2 小时前
C语言之可变参函数
c语言·开发语言
SunkingYang2 小时前
详细介绍C++中捕获异常类型的方式有哪些,分别用于哪些情形,哪些异常捕获可用于通过OLE操作excel异常
c++·excel·mfc·异常捕获·comerror
北冥湖畔的燕雀5 小时前
C++泛型编程(函数模板以及类模板)
开发语言·c++
QX_hao6 小时前
【Go】--map和struct数据类型
开发语言·后端·golang
你好,我叫C小白6 小时前
C语言 循环结构(1)
c语言·开发语言·算法·while·do...while
Evand J8 小时前
【MATLAB例程】基于USBL和DVL的线性回归误差补偿,对USBL和DVL导航数据进行相互补偿,提高定位精度,附代码下载链接
开发语言·matlab·线性回归·水下定位·usbl·dvl
Larry_Yanan9 小时前
QML学习笔记(四十二)QML的MessageDialog
c++·笔记·qt·学习·ui
爱喝白开水a9 小时前
LangChain 基础系列之 Prompt 工程详解:从设计原理到实战模板_langchain prompt
开发语言·数据库·人工智能·python·langchain·prompt·知识图谱