class MyMainWindow : public QMainWindow
{
private:
SomeDependency someDependency;
}
class SomeWidget : public QWidget
{
public:
~SomeWidget()
{
// Use someDependency by getting it from MyMainWindow (or having MyMainWindow pass it in)
}
}
MyMainWindow::MyMainWindow(QWidget* parent)
: QMainWindow(parent)
{
SomeWidget* someWidget = new SomeWidget(this);
}
我遇到了这个模式的问题。 MyMainWindow
拥有 SomeDependency
。 MyMainWindow
在堆上创建一个新的 SomeWidget
并给它一个父 this
。
SomeWidget
的析构函数需要调用SomeDependency
来做一些事情(比如说……当它快要死的时候从依赖项中注销自己)。当小部件正常消失时,这很好用。
但是,当应用程序被终止时,会出现一个奇怪的问题。 MyMainWindow
析构函数首先被调用。它将清理 SomeDependency
。接下来,调用QMainWindow
析构函数。这将清理它的所有 child 。它开始删除其子项,这导致 SomeWidget
被销毁。 SomeWidget::~SomeWidget()
然后调用 SomeDependency
...但它已被销毁,因此应用程序崩溃。
我怎样才能遵守 Qt 父/子内存生命周期规则,但让子从 MyMainWindow
获取它们的依赖项?
最佳答案
最简单的解决方案是做你一直以来应该做的事情:不在堆上分配子部件,除非它们需要动态创建。 C++ 具有明确定义的语义:m_widget
将在 m_dependency
之前被销毁。
class MyMainWindow : public QMainWindow
{
SomeDependency m_dependency;
SomeWidget m_widget;
};
m_widget
将 MyMainWindow
作为父级是完全没问题的。
或者,如果由于某种原因需要动态创建小部件:
class MyMainWindow : public QMainWindow
{
SomeDependency m_dependency;
QScopedPointer<SomeWidget> m_widget;
};
最后,SomeWidget
可以共享 SomeDependency
的所有权:
class MyMainWindow : public QMainWindow
{
QSharedPointer<SomeDependency> m_dependency;
QScopedPointer<SomeWidget> m_widget { m_dependency };
};
class SomeWidget : public QWidget {
QSharedPointer<SomeDependency> m_dependency;
public:
SomeWidget(QScopedPointer<SomeDependency> dep, QWidget * parent = 0) :
m_dependency(dep) {
...
}
};
旁注:确保您确实需要一个QMainWindow
。如果 QDialog
可以,请不要使用它。
关于c++ - 当子部件依赖于父部件时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35299718/