@Andream
2017-07-17T15:54:18.000000Z
字数 1357
阅读 933
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做了两次析构?
这要分两种情况来看:
也就是用new关键字声明的QObject,对象树可以以任意顺序构造。当某个QObject在对象树里被删除的时候(可能是手动delete,可能是C++自动delete),它的爸爸的child列表会同步删除它,同时它的儿子们也会被依次删除。不管以怎样的顺序删除,每个QObject的析构函数都只会被调用一次!
在这种情况下,一般也不会出现问题,比如:
int main()
{
QWidget window;
QPushButton quit("Quit", &window);
...
}
quit 从属于 window,但函数结束时,按照C++的标准,析构的顺序和对象声明的顺序相反,也就是先析构quit,再析构window,每个对象也是只会被析构一次。
但如果我们把对象声明的顺序反过来呢?
int main()
{
QPushButton quit("Quit");
QWidget window;
quit.setParent(&window);
...
}
这下,按照C++标准,window先析构,同时按照Qt从属系统,window析构的时候它的儿子quit也要被析构。但是C++可不知道Qt已经把quit析构了,它还企图对quit再析构一次,这个时候就出问题了(程序崩溃,exit with code 255)。这个地方要特别注意。