我试图在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();
}
我的程序的构建是可以的。但是我收到了运行时错误&#34; QWidget:必须在QWidget&#34;之前构造一个QApplication。我该怎么做才能解决这个问题?我想使用这种形式的单例来创建一个线程安全的程序。
提前感谢您的帮助。
礼
答案 0 :(得分:1)
安全地保存全局对象实例的Qt-idiomatic方法是Q_GLOBAL_STATIC
。该实例是在第一次使用时创建的。这样,在QApplication
实例存在后,将在需要时创建您的单例实例。
而不是MainWindow* MainWindow::uniqueInstance = new MainWindow()
,你写的是:
Q_GLOBAL_STATIC(MainWindow, uniqueInstance);
答案 1 :(得分:1)
根据之前的答案以及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();
}
这是有效的并且是线程安全的。
答案 2 :(得分:-1)
MainWindow* MainWindow::uniqueInstance = new MainWindow();
这是全局实例,它发生在main函数之前,所以这个构造函数早于main函数,这是不允许的。 Qt需要首先构建QApplication,然后构建小部件。所以你需要在构造函数之后将它移动到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,引入了一个新的全局MACRO用于创建这种SINGLETON(Q_GLOBAL_STATIC http://qt-project.org/forums/viewthread/13977),它更优雅,但是,这个宏只存在于Qt5,而不是Qt4,并且还有您应注意的一些使用限制。基本上它也是一个用于包装代码以在运行时创建单例的宏。