简体   繁体   English

单例线程安全程序

[英]Singleton thread-safe programs

I'm trying to write a simple app with singleton design in Qt. 我正在尝试在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". 但是我收到运行时错误“ QWidget:必须在QWidget之前构造一个QApplication”。 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 . 安全地持有线程的全局对象实例的Qt惯用方式是通过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. 这样,在存在QApplication实例之后,将在需要时创建您的单例实例。

Instead of MainWindow* MainWindow::uniqueInstance = new MainWindow() , you'd write: 您可以这样写,而不是MainWindow* MainWindow::uniqueInstance = new MainWindow()

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: 根据先前的答案以及http://doc.qt.io/qt-5/qglobalstatic.html#Q_GLOBAL_STATIC ,答案如下:

#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: .cpp文件如下:

#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. 这是全局实例,它发生在main函数之前,因此此构造函数早于main函数,这是不允许的。 Qt needs to construct QApplication first, then the widget. Qt需要首先构造QApplication,然后构造小部件。 so you need to move this after constructor the QApplication in main, or just remove it. 因此,您需要将其移至main中的QApplication构造函数之后,或将其删除。

MainWindow* MainWindow::uniqueInstance = 0;

then constructor the object after QApplication. 然后在QApplication之后构造对象。

As I said, you should NOT constructor the uniqueInstance before main, modified some code basing on your POST, it should work. 就像我说过的那样,您不应该在main之前构造uniqueInstance,而是基于POST修改一些代码,它应该可以工作。

#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. 在Kuba的POST的基础上,引入了一个新的全局MACRO,用于创建这种SINGLETON(Q_GLOBAL_STATIC http://qt-project.org/forums/viewthread/13977 ),它更为优雅,但是,此宏仅存在于Qt5中,而不是Qt4,并且还有一些使用限制,您应该注意。 Basically it is also a macro for wrapping code to create singleton at runtime. 基本上,它还是用于包装代码以在运行时创建单例的宏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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