72 lines
2.8 KiB
C++
72 lines
2.8 KiB
C++
#ifndef SINGLETON_H
|
||
#define SINGLETON_H
|
||
|
||
#include <QScopedPointer>
|
||
|
||
/**
|
||
* 使用方法:
|
||
* 1. 定义类为单例 (类声明时使用宏 SINGLETON):
|
||
* class HelloWorld {
|
||
* SINGLETON(HelloWorld)
|
||
* public:
|
||
*
|
||
* 2. 在 cpp 文件中实现类的默认构造函数和析构函数 (已经在宏 SINGLETON 里被声明为 private 的了,所以必须实现)
|
||
*
|
||
* 3. 调用单例的函数: HelloWorld::instance()->method()
|
||
*
|
||
* 注意:
|
||
* 1. 单例的创建不是线程安全的
|
||
* 2. 如果单例的类需要释放的资源和 Qt 底层的信号系统有关系,例如 QSettings 的数据没有保存,QSqlDatabase 的连接没有关闭等,
|
||
* 需要在 main 函数返回前手动释放,否则有可能在程序退出时报系统底层的信号错误,因为 main 函数返回后 qApp 已经被回收,
|
||
* 而资源的释放在 main 返回后,又和信号槽有关,所以就可能报错。
|
||
* 推荐实现方式: 可以在单例类的构造函数中给 qApp 的 aboutToQuit 信号绑定一个槽函数,在里面处理善后工作、释放资源等。
|
||
*/
|
||
|
||
template <typename T>
|
||
class Singleton {
|
||
public:
|
||
static T* get_instance() {
|
||
if (s_instance.isNull()) {
|
||
s_instance.reset(new T()); // 此指针会在全局变量作用域结束时自动 deleted (main 函数返回后)
|
||
}
|
||
return s_instance.data();
|
||
}
|
||
|
||
static void destroy_instance() {
|
||
s_instance.reset(nullptr);
|
||
}
|
||
|
||
Singleton(const Singleton& other) = delete;
|
||
Singleton<T>& operator=(const Singleton& other) = delete;
|
||
|
||
private:
|
||
static QScopedPointer<T> s_instance;
|
||
};
|
||
|
||
template <typename T> QScopedPointer<T> Singleton<T>::s_instance;
|
||
|
||
|
||
|
||
/*-----------------------------------------------------------------------------|
|
||
| Singleton Macro |
|
||
|----------------------------------------------------------------------------*/
|
||
#define SINGLETON(Class) \
|
||
private: \
|
||
Class(); \
|
||
~Class(); \
|
||
Class(const Class &other) = delete; \
|
||
Class& operator=(const Class &other) = delete; \
|
||
friend class Singleton<Class>; \
|
||
friend struct QScopedPointerDeleter<Class>; \
|
||
\
|
||
public: \
|
||
static Class* instance() { \
|
||
return Singleton<Class>::get_instance(); \
|
||
} \
|
||
\
|
||
static void destroy_instance() { \
|
||
Singleton<Class>::destroy_instance(); \
|
||
}
|
||
|
||
#endif // SINGLETON_H
|