I wrote the following code, which doesn't provoke any error:
main.cpp
#include "main_window.hpp"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
main_window.hpp
#pragma once
#include "ui_main_window.h"
#include <QtWidgets/QMainWindow>
#include <QGraphicsView>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
setCentralWidget(&view);
}
private:
Ui::MainWindowClass ui;
QGraphicsView view;
};
However, Qt documentation for QMainWindow::setCentralWidget
says that
Note: QMainWindow takes ownership of the widget pointer and deletes it at the appropriate time.
Shouldn't there be a crash on finishing app because of double deleting of view
: by Qt's ownership model and by ~MainWindow()
?
This would work as written. The behavior is well defined.
The way Qt ownership works, every QObject
-derived object keeps a list of the children it owns, as well as a pointer to its parent it is owned by. QObject
destructor then does two things - it destroys all children, and also notifies its parent that it has been destroyed. In response to that, the parent removes this now-destroyed child from its list of owned objects.
In your example, when MainWindow
object is constructed, the base class QObject
constructor runs first, (then other base class constructos), and then constructors of data members, including view
. The destruction proceeds in the reverse order: view
is destroyed first, whereupon it notifies its owner MainWindow
object (or rather, the QObject
base class sub-object within MainWindow
) to remove itself from the list. Then eventually QObject
destructor runs, but by that time a pointer to view
is no longer in the list.
By this mechanism, double deletion is avoided.