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
析构函数。这将清理所有的孩子。它开始删除它的子节点,导致SomeWidget
被销毁。 SomeWidget::~SomeWidget()
然后调用SomeDependency
...但它已被销毁,因此应用程序崩溃。
我如何通过Qt父/子内存生存期规则进行游戏,但让孩子从MyMainWindow
获取其依赖项?
答案 0 :(得分:0)
最简单的解决方案是执行您应该一直执行的操作:不在堆上分配子窗口小部件,除非需要动态创建它们。 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
会这样做,请不要使用它。