Qt:对象树和所有权

1059 篇文章 287 订阅

概述

QObject在对象树中组织自己。当您创建带有另一个对象作为父对象的QObject时,它会添加到父对象的children()列表中,并在父对象被删除时被删除。事实证明,这种方法非常适合GUI的需要。例如,QShortcut(键盘快捷方式)是相关窗口的子级,因此,当用户关闭该窗口时,快捷方式也会被删除。

QQuickItem是Qt Quick模块的基本可视元素,它继承自QObject,但是其可视父对象的概念不同于QObject父对象的概念。项的视觉父项不一定与它的对象父项相同。有关更多详细信息,请参见Qt Quick中的概念-可视化父类

QWidget是Qt Widgets模块的基本类,它扩展了父子关系。自不见通常也会称为子部件,也就是说,它显示在其父部件的坐标系统中,并被其父部件的边界以图形方式剪切。例如,当应用程序在消息框关闭后删除它时,消息框的按钮和标签也会被删除,正如我们所希望的那样,因为按钮和标签是消息框的子元素。

您也可以自己删除子对象,它们将从自己的父对象中删除。比如,当用户删除一个工具栏时,它可能导致应用程序删除它的一个QToolBar对象,在这种情况下,工具栏的QMainWindow父类将检测到更改并相应的重新配置它的屏幕空间。

当应用程序外观或行为异常时,调试功能QObject :: dumpObjectTree()QObject :: dumpObjectInfo()通常很有用。

QObject的构建/销毁顺序

当在堆上创建QObject时(即使用new创建),可以用它们的任何顺序构建树,之后,可以用任何顺序销毁树中的对象。当删除树中的任何QObject时,如果该对象有父对象,析构函数将自动从父对象中删除该对象。如果对象有子对象,析构函数会自动删除每个子对象。无论销毁的顺序如何,QObject都不会被删除两次。

当在堆上创建QObject(即,用new创建)时,可以以任何顺序从它们构造树,然后,可以以任何顺序销毁树中的对象。删除树中的任何QObject时,如果该对象具有父对象,则析构函数会自动从其父对象中删除该对象。如果对象有子对象,则析构函数会自动删除每个子对象。没有QObject中被删除两次,不管破坏的秩序。

在堆栈上创建QObject时,将应用相同的行为。通常,销毁顺序仍然不会出现问题。考虑以下代码段:

int main()
{
    QWidget window;
    QPushButton quit("Quit", &window);
    ...
}

父窗口window和子窗口quit都是QObject,因为QPushButton继承了QWidget, QWidget继承了QObject。此代码是正确的:quit的析构函数不会被调用两次,因为c++语言标准(ISO/IEC 14882:2003)规定局部对象的析构函数调用顺序和它们的构造函数相反。因此,首先调用子函数quit的析构函数,然后在调用window的析构函数之前,将自己从父函数window中移除。

但是现在考虑一下,如果我们交换构造顺序会发生什么,如第二个片段所示:

int main()
{
    QPushButton quit(("Quit");
    
    QWidget window;;

    quit.setParent((&window);
    );
    ...
}}

在这种情况下,析构的顺序会引起问题。父级的析构函数首先被调用,因为它是最后创建的。然后,它调用其子项quit的析构函数,这是不正确的,因为quit是一个局部变量。当quit随后超出作用域时,它的析构函数将再次被调用,这一次是正确的,但损害已经造成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值