[关闭]
@Andream 2017-07-17T15:54:18.000000Z 字数 1357 阅读 933

【Qt学习笔记】1.1.4 对象树(对象所属关系)

Qt


本文为Qt官方文档译文,查看原文

Qt的许多许多的QObject之间,有一种特殊的组织方式:从属树(Ownership)。对象之间可以认爸爸认儿子,这和继承关系不一样,是Qt对QObject拓展的一个性质:即从属关系。如果ObjectA认ObjectB当爸爸,ObjectA就被添加到ObjectB的children()列表里面。当ObjectB被销毁的时候,ObjectA也会一同陪葬(这就表现出了所属关系)。

有了从属关系,对GUI编程大有好处。比如,把一个QShortcut(键盘快捷键对象)设置为它关联的window对象的儿子,那么当window关闭的时候,这个shortcut也被删除,也就失效了。这是很实用的。

GUI中的QQuickItem,是Qt Quick模块中的最基础的视图元素。它继承自QObject,但是它并不从属于QObject,而是从属于另一个视图元素,比如Layout。这样,视图的层次关系就定义下来了。

GUI中的QWidget,是Qt Widgets模块中的基础类。和Qt Quick类似,QWidget之间也有从属关系,也对应着视图显示的层级关系。

你可以通过添加从属关系,来建立起视图层次,也可以删除从属关系,动态的去掉某些视图。比如,用户可以在设置中隐藏工具栏,其实就是把QMainWindow里的QToolBar这个儿子移除了,然后重新刷新视图就成了。

QObject::dumpObjectTree() 和 QObject::dumpObjectInfo()这两个函数能导出所有QObject的信息,也可以用来调试!

构造/析构规则

假设我们现在有很多QObject,他们之间有某种从属关系,那他们在构造和析构的时候是否要满足一定的顺序呢?会不会一不小心对同一个QObject做了两次析构?
这要分两种情况来看:

QObject在堆内存中

也就是用new关键字声明的QObject,对象树可以以任意顺序构造。当某个QObject在对象树里被删除的时候(可能是手动delete,可能是C++自动delete),它的爸爸的child列表会同步删除它,同时它的儿子们也会被依次删除。不管以怎样的顺序删除,每个QObject的析构函数都只会被调用一次!

QObject在栈内存中

在这种情况下,一般也不会出现问题,比如:

  1. int main()
  2. {
  3. QWidget window;
  4. QPushButton quit("Quit", &window);
  5. ...
  6. }

quit 从属于 window,但函数结束时,按照C++的标准,析构的顺序和对象声明的顺序相反,也就是先析构quit,再析构window,每个对象也是只会被析构一次。

但如果我们把对象声明的顺序反过来呢?

  1. int main()
  2. {
  3. QPushButton quit("Quit");
  4. QWidget window;
  5. quit.setParent(&window);
  6. ...
  7. }

这下,按照C++标准,window先析构,同时按照Qt从属系统,window析构的时候它的儿子quit也要被析构。但是C++可不知道Qt已经把quit析构了,它还企图对quit再析构一次,这个时候就出问题了(程序崩溃,exit with code 255)。这个地方要特别注意。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注