Qt 核心功能(03):对象树和所有权【官翻】

博客介绍了QObject将自己组织在对象树中,创建时添加到父对象列表,父对象删除时子对象也会被删除。QQuickItem和QWidget有不同特点,还可手动删除子对象。同时阐述了在堆和堆栈上创建QObject时的构建/销毁顺序及可能出现的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对象树和所有权

概述

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

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

QWidget是Qt Widgets模块的基本类,它扩展了父子关系。通常,子级也将成为子级小部件,即在其父级的坐标系中显示,并通过其父级的边界以图形方式进行裁剪。例如,当应用程序在关闭后删除消息框时,消息框的按钮和标签也会被删除,就像我们想要的那样,因为按钮和标签是消息框的子级。

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

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

构建/销毁QObject的顺序

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

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

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

窗口和子窗口都是QObject,因为QPushButton继承了QWidget,而QWidget继承了QObject。 这段代码是正确的:quit的析构函数不会被调用两次,因为C ++语言标准(ISO / IEC 14882:2003)指定以与它们的构造函数相反的顺序调用本地对象的析构函数。 因此,首先调用子项的析构函数quit,然后在调用window的析构函数之前将其从其父窗口中删除。

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

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

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

这种情况下,析构的顺序造成了一个问题。首先调用父级的析构函数,因为它是最后创建的。然后调用它的子部件quit的析构函数,这是不正确的,因为quit是一个局部变量。当quit随后超出范围时,它的析构函数再次被调用,这次是正确的,但是析构已经发生过了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值