简体   繁体   中英

Singleton thread-safe programs

I'm trying to write a simple app with singleton design in Qt. Below is the header file:

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    static MainWindow *getInstance();
    ~MainWindow();

private:
    explicit MainWindow(QWidget *parent = 0);
    static MainWindow *uniqueInstance;
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

And here is implementation file:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow* MainWindow::uniqueInstance = new MainWindow();


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

MainWindow* MainWindow::getInstance()
{
    return uniqueInstance;
}

Finally here is the main function:

#include <QApplication>
#include "mainwindow.h"

#include "QThread"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    MainWindow *w = MainWindow::getInstance();
    w->show();

    return a.exec();
}

Building of my program is OK. But I receive a run-time error "QWidget: Must construct a QApplication before a QWidget". What should I do for solving this problem? I want to use this form of singleton to have a thread-safe program.

Thanks in advance for your helps.

Reza

The Qt-idiomatic way of holding a global object instance thread-safely is through Q_GLOBAL_STATIC . The instance is created on the first use. This way, your singleton instance will be created when needed, after QApplication instance exists.

Instead of MainWindow* MainWindow::uniqueInstance = new MainWindow() , you'd write:

Q_GLOBAL_STATIC(MainWindow, uniqueInstance);

Based on previous answers and also http://doc.qt.io/qt-5/qglobalstatic.html#Q_GLOBAL_STATIC , the answer is like below:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
    friend class myClass;

public:
    static MainWindow *getInstance();
    ~MainWindow();

private:

    explicit MainWindow(QWidget *parent = 0);
    Ui::MainWindow *ui;
};

class myClass : public MainWindow
{
};

#endif // MAINWINDOW_H

.cpp file is like below:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QGlobalStatic>

Q_GLOBAL_STATIC(myClass,uniqueInstance)

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

MainWindow* MainWindow::getInstance()
{
    return uniqueInstance;
}

finally main file is like below:

#include <QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    MainWindow *w = MainWindow::getInstance();
    w->show();

    return a.exec();
}

And that works and is thread-safe.

MainWindow* MainWindow::uniqueInstance = new MainWindow();

this is global instance, it happens before the main function, so this constructor is earlier than the main function, which is not allowed. Qt needs to construct QApplication first, then the widget. so you need to move this after constructor the QApplication in main, or just remove it.

MainWindow* MainWindow::uniqueInstance = 0;

then constructor the object after QApplication.

As I said, you should NOT constructor the uniqueInstance before main, modified some code basing on your POST, it should work.

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow* MainWindow::uniqueInstance = 0;


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

MainWindow* MainWindow::getInstance()
{
    if (0 == MainWindow::uniqueInstance){
        MainWindow::uniqueInstance = new MainWindow();
    }
    return MainWindow::uniqueInstance;
}

Basing on Kuba's POST, there is introduced a new global MACRO for creating this kind of SINGLETON (Q_GLOBAL_STATIC http://qt-project.org/forums/viewthread/13977 ), it is more elegant, however, this macro only exists in Qt5, not Qt4, and also has some usage limit you should notice. Basically it is also a macro for wrapping code to create singleton at runtime.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM