Skip to content
nucularmoo edited this page Mar 20, 2018 · 19 revisions

Parent-Child relationship

Explanation of the contents of a topic page @ Week 1 Topic 1

Back to Week 1

Objective: Qt memory management with object trees

Comment: Looks good already, no further comments at this point.

Beginner

  • What is a pointer?
  • What is a null pointer?
  • What is "on stack"?
  • What is "on heap"?

Intermediate

  • What is the object tree?
  • How construct/destruct object trees?
  • What happens when you create objects?
  • What happens when you delete objects?
  • What is the difference between creating objects on stack and on heap?
  • What is "the dangling pointer problem"?
  • Does the object tree solve "the dangling pointer problem"?
  • What happens to my pointers when I delete objects?

Expert


Course material content

The Object Tree

http://doc.qt.io/qt-5/objecttrees.html

QObjects organize themselves in object trees. When you create a QObject with another object as parent, it's added to the parent's children() list, and is deleted when the parent is. It turns out that this approach fits the needs of GUI objects very well. For example, a QShortcut (keyboard shortcut) is a child of the relevant window, so when the user closes that window, the shortcut is deleted too.

QQuickItem, the basic visual element of the Qt Quick module, inherits from QObject, but has a concept of the visual parent which differs from that of the QObject parent. An item's visual parent may not necessarily be the same as its object parent. See Concepts - Visual Parent in Qt Quick for more details.

QWidget, the fundamental class of the Qt Widgets module, extends the parent-child relationship. A child normally also becomes a child widget, i.e. it is displayed in its parent's coordinate system and is graphically clipped by its parent's boundaries. For example, when the application deletes a message box after it has been closed, the message box's buttons and label are also deleted, just as we'd want, because the buttons and label are children of the message box.

You can also delete child objects yourself, and they will remove themselves from their parents. For example, when the user removes a toolbar it may lead to the application deleting one of its QToolBar objects, in which case the tool bar's QMainWindow parent would detect the change and reconfigure its screen space accordingly.

Object and pointer permanence

http://doc.qt.io/qt-5/objecttrees.html#construction-destruction-order-of-qobjects

When QObjects are created on the heap (i.e., created with new), a tree can be constructed from them in any order, and later, the objects in the tree can be destroyed in any order. When any QObject in the tree is deleted, if the object has a parent, the destructor automatically removes the object from its parent. If the object has children, the destructor automatically deletes each child. No QObject is deleted twice, regardless of the order of destruction.

When QObjects are created on the stack, the same behavior applies. Normally, the order of destruction still doesn't present a problem. Consider the following snippet:

int main() { QWidget window; QPushButton quit("Quit", &window); ... } The parent, window, and the child, quit, are both QObjects because QPushButton inherits QWidget, and QWidget inherits QObject. This code is correct: the destructor of quit is not called twice because the C++ language standard (ISO/IEC 14882:2003) specifies that destructors of local objects are called in the reverse order of their constructors. Therefore, the destructor of the child, quit, is called first, and it removes itself from its parent, window, before the destructor of window is called.

But now consider what happens if we swap the order of construction, as shown in this second snippet:

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

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

In this case, the order of destruction causes a problem. The parent's destructor is called first because it was created last. It then calls the destructor of its child, quit, which is incorrect because quit is a local variable. When quit subsequently goes out of scope, its destructor is called again, this time correctly, but the damage has already been done.

To summarize:

  • Tree can be constructed in any order
  • Tree can be destroyed in any order
  • if object has parent: object first removed from parent
  • if object has children: deletes each child first
  • No object is deleted twice

Please note that Parent-child relationship is NOT inheritance.

The Dangling Pointer

https://stackoverflow.com/questions/17997228/what-is-a-dangling-pointer

The object tree does not solve the dangling pointer problem. QPointer provides a guarded pointer for QObject. When the referenced object destroyed, it sets the pointer to 0. It can be easy to mix guarded and normal pointers The guarded pointer is automatically cast to the pointer type.

Qt objects may also notify observers just before their destruction.


Instructions and description for the exercise of topic 1.04

TBA

Exhaustive reference material mentioned in this topic

Further reading topics/links:

Clone this wiki locally