【问题标题】:Qt singleton twice destructor callQt单例两次析构函数调用
【发布时间】:2014-05-18 02:15:21
【问题描述】:

我必须在我的应用程序中为小部件使用单例模式。 所以我已经为此做了实现。

testwidget.h

class TestWidget;

class TstWidgetHolder
{
static TestWidget* wobj;
public:
    static const TestWidget* instance();
    static void setParent(QWidget*);
};

class TestWidget : public QWidget
{
   Q_OBJECT
   friend class TstWidgetHolder;
private:
   Ui::TestWidget ui;

   explicit TestWidget(QWidget *parent = 0);
   ~TestWidget();
 };

testwidget.cpp

TestWidget::TestWidget(QWidget *parent) :
    QWidget(parent)
{
    ui.setupUi(this);
}

TestWidget::~TestWidget() 
{}

TestWidget* TstWidgetHolder::wobj = NULL;
void TstWidgetHolder::setParent(QWidget* obj)
{
   static TestWidget tst(obj);
   TstWidgetHolder::wobj = &tst;
}
const TestWidget* TstWidgetHolder::instance()
{
   return wobj;
}

就这么简单。 然后是我正在为这个单例设置父程序的主程序。

TstWidgetHolder::setParent(this);

真正的问题来了。 当主窗口小部件关闭时,应用程序崩溃。

根据调试器,单例小部件的析构函数被调用了两次。 这当然是导致崩溃的原因。

有什么问题? 是 Qt 中的 bug 还是我的逻辑?

HERE SOURCE CODE

【问题讨论】:

  • 两个建议:首选the Meyers singleton 而不是动态分配方法。第二:如果你这样做,从不返回一个指针,通过引用返回。直接返回指针允许单例用户执行delete singleton::instance() 之类的操作。
  • 你如何使用TstWidgetHolder?您是否多次致电setParent
  • singleton 设计模式是最简单且最被过度使用的模式,并且可能是最糟糕的模式(经常产生问题并且优势有限)。我建议尽可能避免它。无论如何,如果某物是单例,则它不能有父对象,因为它是根对象。

标签: c++ qt inheritance singleton destructor


【解决方案1】:

当您创建TstWidgetHolder::setParent(this) 时,您就是将TestWidget 实例的所有权(换句话说,销毁的责任)委托给this。所以,就在this 指向的对象被破坏之前,它会尝试delete tst,这是一个静态 对象......而那个 是你的应用程序崩溃。要么不使用setParent,要么将TstWidgetHolder::setParent 更改为:

void TstWidgetHolder::setParent(QWidget* obj)
{
   TstWidgetHolder::wobj = new TestWidget(obj);
}

【讨论】:

  • 谢谢。那么,是什么让这个委托过程成为可能呢?是不是一些不明显的生成代码特性?因为就我在没有 Qt 的情况下测试过的这种方法而言,它是有效的。
  • 没有那么复杂。 :D 查看 Qt 的源代码,您会看到 ~QObject 析构函数会破坏对象的所有子对象。因为每个QWidget 都是QObject...:D
猜你喜欢
  • 2010-12-29
  • 1970-01-01
  • 2015-02-25
  • 2012-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-19
  • 2012-08-06
相关资源
最近更新 更多