单例线程安全程序
Singleton thread-safe programs
我正在尝试用 Qt 中的单例设计编写一个简单的应用程序。下面是头文件:
#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
这里是实现文件:
#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;
}
最后是主要功能:
#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();
}
我的程序构建正常。但是我收到 运行 次错误 "QWidget: Must construct a QApplication before a QWidget"。我应该怎么做才能解决这个问题?我想用这种形式的单例来做一个线程安全的程序。
在此先感谢您的帮助。
礼萨
MainWindow* MainWindow::uniqueInstance = new MainWindow();
这是全局实例,发生在main函数之前,所以这个构造函数早于main函数,这是不允许的。 Qt 需要先构建QApplication,然后再构建widget。所以你需要在 main 中的构造函数 QApplication 之后移动它,或者只是删除它。
MainWindow* MainWindow::uniqueInstance = 0;
然后在QApplication之后构造对象。
正如我所说,您不应该在 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;
}
在Kuba的POST的基础上,引入了一个新的全局宏来创建这种SINGLETON(Q_GLOBAL_STATIC http://qt-project.org/forums/viewthread/13977),更优雅,但是,这个宏只是存在于 Qt5,而不是 Qt4,并且还有一些您应该注意的使用限制。基本上它也是一个宏,用于包装代码以在运行时创建单例。
线程安全地持有全局对象实例的 Qt 惯用方法是通过 Q_GLOBAL_STATIC
。该实例是在第一次使用时创建的。这样,您的单例实例将在需要时创建,在 QApplication
个实例存在之后。
而不是 MainWindow* MainWindow::uniqueInstance = new MainWindow()
,你会写:
Q_GLOBAL_STATIC(MainWindow, uniqueInstance);
根据之前的回答以及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 文件如下:
#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;
}
最终主文件如下:
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow *w = MainWindow::getInstance();
w->show();
return a.exec();
}
这有效并且是线程安全的。
我正在尝试用 Qt 中的单例设计编写一个简单的应用程序。下面是头文件:
#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
这里是实现文件:
#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;
}
最后是主要功能:
#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();
}
我的程序构建正常。但是我收到 运行 次错误 "QWidget: Must construct a QApplication before a QWidget"。我应该怎么做才能解决这个问题?我想用这种形式的单例来做一个线程安全的程序。
在此先感谢您的帮助。
礼萨
MainWindow* MainWindow::uniqueInstance = new MainWindow();
这是全局实例,发生在main函数之前,所以这个构造函数早于main函数,这是不允许的。 Qt 需要先构建QApplication,然后再构建widget。所以你需要在 main 中的构造函数 QApplication 之后移动它,或者只是删除它。
MainWindow* MainWindow::uniqueInstance = 0;
然后在QApplication之后构造对象。
正如我所说,您不应该在 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;
}
在Kuba的POST的基础上,引入了一个新的全局宏来创建这种SINGLETON(Q_GLOBAL_STATIC http://qt-project.org/forums/viewthread/13977),更优雅,但是,这个宏只是存在于 Qt5,而不是 Qt4,并且还有一些您应该注意的使用限制。基本上它也是一个宏,用于包装代码以在运行时创建单例。
线程安全地持有全局对象实例的 Qt 惯用方法是通过 Q_GLOBAL_STATIC
。该实例是在第一次使用时创建的。这样,您的单例实例将在需要时创建,在 QApplication
个实例存在之后。
而不是 MainWindow* MainWindow::uniqueInstance = new MainWindow()
,你会写:
Q_GLOBAL_STATIC(MainWindow, uniqueInstance);
根据之前的回答以及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 文件如下:
#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;
}
最终主文件如下:
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow *w = MainWindow::getInstance();
w->show();
return a.exec();
}
这有效并且是线程安全的。