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拥有SomeDependencyMyMainWindow在堆上创建一个新的SomeWidget,并为其提供父级this

SomeWidget的析构函数需要调用SomeDependency来执行某项操作(例如,在死时将其自身从依赖项中注销)。当小部件正常消失时,此方法工作正常。

但是,当该应用程序被杀死时,就会出现一个奇怪的问题。首先调用MyMainWindow析构函数。它将清除SomeDependency。接下来,调用QMainWindow析构函数。这将清理其所有子级。它开始删除其子级,从而导致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/

10-11 21:28