Qt 單例模式的實現 ,自定義巨集實現方法
阿新 • • 發佈:2021-12-05
最簡單的寫法:
static MyClass* MyClass::Instance() { static MyClass inst; return &inst; }
進階寫法:
static MyClass* MyClass::Instance() { static QMutex mutex; static QScopedPointer<MyClass> inst; if (Q_UNLIKELY(!inst)) { mutex.lock(); if (!inst) { inst.reset(new MyClass); } mutex.unlock(); } return inst.data(); }
既保證了執行緒安全又防止了記憶體洩漏,效率也沒降低太多,簡直完美。
可惜每次都要重複這麼幾行實在麻煩,於是寫了一個
範型模板類:
template <class T> class Singleton { public: static T* Instance() { static QMutex mutex; static QScopedPointer<T> inst;if (Q_UNLIKELY(!inst)) { mutex.lock(); if (!inst) { inst.reset(new T); } mutex.unlock(); } return inst.data(); } };
使用的時候直接這樣:
MyClass* inst = Singleton<MyClass>::Instance();
除了用模板類,還可以利用c++中強大的巨集:
#define DECLARE_SINGLETON(Class) \ Q_DISABLE_COPY(Class) \public: \ static Class* Instance() \ { \ static QMutex mutex; \ static QScopedPointer<Class> inst; \ if (Q_UNLIKELY(!inst)) { \ mutex.lock(); \ if (!inst) inst.reset(new Class); \ mutex.unlock(); \ } \ return inst.data(); \ }
然後宣告的時候,填加一行這個巨集:
class MyClass { DECLARE_SINGLETON(MyClass); // 宣告單例模式 //... }
當然,為了要保證真的是單例模式,還要把建構函式限制為private,不然以後什麼時候忘記了這碼事,在外面又new了一下就不好了。
另外Qt本身自帶了一個巨集
Q_GLOBAL_STATIC
,也有類似單例模式的效果,QThreadPool::globalInstance()
函式的實現就是利用了這個巨集。不過它的主要用處是宣告全域性變數,和Singleton還是有差別的。