Qt 之 对象树与所有权

Qt助手搜索:Object Trees & Ownership 可阅读原文。

概述

QObjects在一个对象树中组织他们自己。当你创建一个以另一个对象作为其父对象的QObject对象时,它被添加到父对象的children()列表中,并且该对象随着其父对象的销毁而销毁。事实表明,这种机制非常适合管理GUI对象。例如,一个QShortcut(键盘快捷键)对象是相关窗口的一个子对象,因此,当用户关闭该窗口时,快捷键也会被销毁。

QQuickItem, the basic visual element of the Qt Quick module, inherits from QObject, but has a concept of the visual parent which differs from that of the QObject parent. An item’s visual parent may not necessarily be the same as its object parent. See Concepts - Visual Parent in Qt Quick for more details.

QWidget, the fundamental class of the Qt Widgets module, extends the parent-child relationship. A child normally also becomes a child widget, i.e. it is displayed in its parent’s coordinate system and is graphically clipped by its parent’s boundaries. For example, when the application deletes a message box after it has been closed, the message box’s buttons and label are also deleted, just as we’d want, because the buttons and label are children of the message box.

当然,你也可以自己删除子对象,他们会从父对象的children()列表中移除自己。例如,when the user removes a toolbar it may lead to the application deleting one of its QToolBar objects, in which case the tool bar’s QMainWindow parent would detect the change and reconfigure its screen space accordingly.

The debugging functions QObject::dumpObjectTree() and QObject::dumpObjectInfo() are often useful when an application looks or acts strangely.

QObjects的构造/析构顺序

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

当在栈上创建QObjects时,同样的行为也适用。通常情况下,销毁顺序仍然不会出现问题。看下面的代码:

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

父对象window和子对象quit都属于QObjects,因为QPushButton继承自QWidget,而QWidget继承自QObject。这段代码是正确的:quit的析构函数不会被调用两次,因为C++语言标准(ISO/IEC 14882:2003) 指定本地对象(局部变量)析构函数的调用顺序与构造函数的调用顺序相反。因此,先调用子对象quit的析构函数,并从父对象window的children()列表中移除它自己,然后调用父对象window的析构函数。
如果我们调换构造顺序会发生什么?看下面的代码:

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

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

在这种情况下,销毁的顺序会引起一个问题。先调用父对象的析构函数,因为它是最后创建的。父对象然后调用了子对象quit的析构函数,这是错误的,因为quit是一个局部变量,而delete &quit是错误的。当quit随后超出其作用域,其析构函数再次被调用,这次是正确的,但是错误已经发生了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值