Eltern-Objekte und ihr Einfluss

QObject-Objekten kann über den Konstruktor bzw. die Methode setParent() ein Elternobjekt zugewiesen werden. Dadurch ändern sich zwei wichtige Dinge für das Kindobjekt.

Freigabe von Speicher

Wenn ein QObject-Objekt gelöscht wird, löscht es automatisch seine Kinder. Damit kann man Speicherlecks verhindern, es kann aber auch zu scheinbar unerklärlichen Abstürzen kommen, wenn man sich dessen nicht bewusst ist. Im folgenden Beispielprogramm erstellen wir eine Eltern- und Kindklasse, die beide von QObject abgeleitet sind. Sie haben keine besondere Funktion, lediglich Ausgaben in deren Konstruktoren und Desktruktoren.

// main.cpp
#include "ParentObject.h"
#include "ChildObject.h"
 
int main()
{
  ParentObject *parentObj = new ParentObject();         // Elternobjekt anlegen
  ChildObject *childObj = new ChildObject( parentObj ); // Kindobjekt mit Elternobjekt anlegen
 
  delete parentObj;         // Elternobjekt löschen
 
  return 0;
}
// ParentObject.h
#ifndef PARENTOBJECT_H
#define PARENTOBJECT_H
 
#include <QObject>
#include <iostream>
 
class ParentObject : public QObject
{
 
  public:
    ParentObject();
    ~ParentObject();
 
};
 
#endif
// ParentObject.cpp
#include "ParentObject.h"
 
ParentObject::ParentObject()
{
  std::cout << "Elternobjekt erstellt" << std::endl;
}
 
 
ParentObject::~ParentObject()
{
  cout << "Elternobjekt zerstoert" << endl;
}
// ChildObject.h
#ifndef CHILDOBJECT_H
#define CHILDOBJECT_H
 
#include "ParentObject.h"
#include <QObject>
#include <iostream>
 
class ChildObject : public QObject
{
 
  public:
    ChildObject( ParentObject *parent );  // Elternobjekt muss über Konstruktor festgelegt werden
    ~ChildObject();
 
};
 
#endif
// ChildObject.cpp
#include "ChildObject.h"
 
// Elternobjekt an Basisklassen-Konstruktor weitergeben
ChildObject::ChildObject( ParentObject *parent ) : QObject( parent )
{
  std::cout << "Kindobjekt erstellt" << std::endl;
}
 
 
ChildObject::~ChildObject()
{
  std::cout << "Kindobjekt zerstoert" << std::endl;
}

Ausgabe:

Elternobjekt erstellt
Kindobjekt erstellt
Elternobjekt zerstoert
Kindobjekt zerstoert

Da das Elternobjekt das Kindobjekt löscht kommt es hier auch nicht zu einem Speicherleck. Würden wir das Kindobjekt nach dem Elternobjekt löschen würde das zu einem Programmabsturz führen (Segmentation fault). Umgekehrt können Kinder jedoch bedenkenlos vor ihren Eltern gelöscht werden.
Das bedeutet für das obige Beispiel:

Funktioniert:

  delete childObj;          // Kindobjekt löschen
  delete parentObj;         // Elternobjekt löschen

Funktioniert nicht:

  delete parentObj;         // Elternobjekt löschen
  delete childObj;          // Kindobjekt löschen

Grafischer Einfluss

Bei der Erstellung von grafischen Oberflächen haben Elternobjekte verschiedene, typabhängige Einflüsse auf Kindobjekte. Ein Layout kann z.B. direkt auf ein Widget angewandt werden, indem man das Widget als sein Parentobjekt angibt. Ein weiterer Fall wären grafische Listen bei denen Elemente durch Angabe der Liste als Parentobjekt automatisch in sie eingefügt werden. Die wichtigsten dieser Beziehungen werden im weiteren Verlauf dieses Tutorials behandelt.