为什么在 QMainWindow 中指定成员控件作为中央控件时不会崩溃?

问题描述 投票:0回答:1

我编写了以下代码,它不会引发任何错误:

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;
};

但是,

QMainWindow::setCentralWidget
的 Qt 文档说

注意:QMainWindow 获得小部件指针的所有权并在适当的时间将其删除。

由于 Qt 所有权模型和

view
的双重删除
~MainWindow()
,完成应用程序时不应该发生崩溃吗?

c++ qt qobject ownership-semantics
1个回答
4
投票

这将按所写的那样工作。行为已明确定义。

Qt 所有权的工作方式是,每个

QObject
派生的对象都保留它所拥有的子对象的列表,以及指向它所拥有的父对象的指针。然后,
QObject
析构函数会做两件事 - 它销毁所有子级,并通知其父级它已被销毁。作为回应,父级将这个现已被销毁的子级从其拥有的对象列表中删除。

在您的示例中,当构造

MainWindow
对象时,首先运行基类
QObject
构造函数(然后是其他基类构造函数),然后是数据成员的构造函数,包括
view
。销毁按相反的顺序进行:首先销毁
view
,然后通知其所有者
MainWindow
对象(或者更确切地说,
QObject
中的
MainWindow
基类子对象)将其自身从列表中删除。然后最终
QObject
析构函数运行,但那时指向
view
的指针不再在列表中。

通过这种机制,避免了双重删除。

© www.soinside.com 2019 - 2024. All rights reserved.