Spec-Zone.ru › Qt

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

Обзор

QObjects организуются в деревья объектов. Когда вы создаете QObject с другим объектом в качестве родителя, он добавляется в список детей() родителя и удаляется при удалении родителя. Этот подход отлично подходит для 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/qt-6.2/objecttrees.html

Spec-Zone.ru

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