Spec-Zone.ru › Qt 5.9

Деревья объектов и владение

Обзор

QObjects организуются в деревья объектов. При создании QObject с другим объектом в качестве родителя, он добавляется в список children() родительского объекта, и удаляется при удалении родителя. Этот подход отлично подходит для объектов GUI. Например, QShortcut (горячая клавиша) является дочерним объектом соответствующего окна, поэтому при закрытии окна горячая клавиша также удаляется.

QQuickItem, базовый визуальный элемент модуля Qt Quick, наследует от QObject, но имеет понятие визуального родителя, которое отличается от родителя QObject. Визуальный родитель элемента необязательно совпадает с его родительским объектом. Подробнее см. Концепции - Визуальный родитель в Qt Quick.

QWidget, базовый класс модуля Qt Widgets, расширяет отношения родитель-потомок. Дочерний объект обычно также становится дочерним виджетом, т.е. отображается в системе координат родительского виджета и графически ограничивается границами родителя. Например, когда приложение удаляет диалоговое окно после его закрытия, кнопки и метка диалогового окна также удаляются, как и ожидалось, так как кнопки и метка являются дочерними объектами диалогового окна.

Вы также можете сами удалить дочерние объекты, и они будут удалены из своих родителей. Например, при удалении пользователем панели инструментов приложение может удалить один из своих объектов QToolBar, в этом случае родительский объект QMainWindow панели инструментов обнаружит изменение и соответствующим образом переконфигурирует своё экранное пространство.

Функции отладки QObject::dumpObjectTree() и QObject::dumpObjectInfo() часто полезны, когда приложение ведет себя странно.

Порядок создания/удаления QObjects

Когда QObjects создаются на куче (т.е. создаются с помощью new), дерево можно построить в любом порядке, а затем объекты в дереве можно удалить в любом порядке. При удалении любого QObject в дереве, если у объекта есть родитель, деструктор автоматически удаляет объект из его родителя. Если у объекта есть дочерние объекты, деструктор автоматически удаляет каждый дочерний объект. Ни один 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, перед вызовом деструктора window.

Но теперь рассмотрим, что произойдет, если мы поменяем порядок создания, как показано во втором фрагменте:

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

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

В этом случае порядок удаления создаёт проблему. Деструктор родителя вызывается первым, потому что он был создан последним. Затем он вызывает деструктор своего дочернего объекта, quit, что неверно, потому что quit - это локальная переменная. Когда quit выходит из области видимости, его деструктор вызывается снова, на этот раз правильно, но ущерб уже нанесен.

© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/archives/qt-5.6/objecttrees.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API