0

I've to use Singleton pattern for widget in my app. So I've made implementation for this.

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

As simple as this. Then is main program I'm setting up parent to this singleton.

TstWidgetHolder::setParent(this);

And there the real problem comes. When main widget closes, application crashes.

According to debugger, the destructor of singleton widget is being called twice. And that's of course is the cause of crash.

What's the problem? Is it bug in Qt or mine logic?

HERE SOURCE CODE

quadraSix
  • 23
  • 5
  • Two advises: Prefer [the Meyers singleton](http://stackoverflow.com/questions/1661529/is-meyers-implementation-of-singleton-pattern-thread-safe) over the dynamic allocation approach. Second: If you do the later, **never** return a pointer, return by reference. Returning the pointer directly allows the user of the singleton to do something like `delete singleton::instance()`. – Manu343726 Apr 05 '14 at 19:00
  • How do you use `TstWidgetHolder`? Are you calling `setParent` multiple times? – Some programmer dude Apr 05 '14 at 19:01
  • The `singleton` design pattern is simples and most OVERUSED pattern ever and possibly most crappy one (often produces problems and have limited advantages). I recommend to avoid it as much as possible. Anyway if something is a singleton it can't have a parent since it is a root object. – Marek R Apr 05 '14 at 21:28

1 Answers1

0

When you make TstWidgetHolder::setParent(this) you are delegating ownership (in other words, responsability to destruct) of the TestWidget instance to this. So, right before the object pointed to by this is destructed, it tries to delete tst, which is an static object... and that is what makes your application crash. Either you don't use setParent or you should change TstWidgetHolder::setParent to:

void TstWidgetHolder::setParent(QWidget* obj)
{
   TstWidgetHolder::wobj = new TestWidget(obj);
}
Massa
  • 8,647
  • 2
  • 25
  • 26
  • Thank's. So, what makes this delegate process possible? Is it some unobvious generated code features? Because as far as I tested this approach without Qt it works. – quadraSix Apr 05 '14 at 19:41
  • 1
    Nothing so convoluted. :D Looking at Qt's source code, you'll see that the `~QObject` destructor destroys all children of an object. As every `QWidget` is a `QObject`... :D – Massa Apr 05 '14 at 22:07