Qt对象树和所有权

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wyy626562203/article/details/82759174

Qt对象树和所有权

Qt 5.10.1

概述

每一个QObject都有自己的一颗对象树。当您使用另一个对象作为父对象创建QObject时,它将添加到父对象的children()列表中,并在父对象被删除children列表中的对象也会被删除,。事实证明,这种方法很好地满足了GUI对象的需求。例如,QShortcut(键盘快捷键)是相关窗口的子项,因此当用户关闭该窗口时,也会删除快捷键。
QQuickItemQt Quick模块的基本可视元素,继承自QObject,但其visual parent的概念与QObject parent的概念不同。一个元素的visual parent可能不一定与其object parent相同。有关详细信息,请参阅 Concepts - Visual Parent in Qt Quick.

QWidgetQt Widgets模块的基础类,它扩展了parent-child系。一个child通常也会成为一个子窗口部件,即它显示在其父坐标系中,并由其父边界以图形方式剪裁。例如,当应用程序在关闭后删除消息框时,消息框的按钮和标签也会被删除,就像我们想要的那样,因为按钮和标签是消息框的子项。

您也可以自己删除子对象,并将自己从parent身上移除。例如,当用户删除工具栏时,它可能导致应用程序删除其中一个QToolBar对象,在这种情况下,工具栏的QMainWindow父级将检测到更改并相应地重新配置其屏幕空间。
当应用程序外观或行为异常的时候,调试函数QObject::dumpObjectTree()QObject::dumpObjectInfo()通常很有用。

QObjects的构造/销毁顺序

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

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

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

父项,窗口和子项quit都是QObject,因为QPushButton继承了QWidget,而QWidget继承了QObject。 此代码是正确的:退出的析构函数不会被调用两次,因为C++语言标准(ISO / IEC 14882:2003)指定本地对象的析构函数以其构造函数的相反顺序调用。 因此,首先调用子进程的析构函数quit,并在调用窗口的析构函数之前将其自身从其父窗口中删除。
但是现在考虑如果我们交换构造顺序会发生什么,如第二个片段所示:

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

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

在这种情况下,销毁顺序会导致问题。 首先调用父的析构函数,因为它是最后创建的。 然后它调用其子项quit的析构函数,这是不正确的,因为quit是一个局部变量。 当quit被销毁后,他的析构函数又被调用了一次,这一次才正常的调用,不过这可能会导致程序的崩溃!

猜你喜欢

转载自blog.csdn.net/wyy626562203/article/details/82759174