C++單例模式的模板基類
阿新 • • 發佈:2018-11-10
單例模式是很常用的設計模式,如果希望系統中某個類的物件只能有一個或者有一個就夠了,那麼便可以採用單例模式來解決。
下面用C++實現一個單例模板類,那麼其他的類只需繼承它,便可以成為單例類。
本例中使用了 CMutex類,是考慮多執行緒的情況,這個類的定義請參見筆者的另一篇部落格《C++簡單封裝互斥量》,
下面用C++實現一個單例模板類,那麼其他的類只需繼承它,便可以成為單例類。
本例中使用了 CMutex類,是考慮多執行緒的情況,這個類的定義請參見筆者的另一篇部落格《C++簡單封裝互斥量》,
連結 http://blog.csdn.net/kentzhang_/article/details/48180865
程式碼如下:
BaseSingleton.h
/************************************************************************* > File Name: BaseSingleton.h > Author: KentZhang > Mail:
[email protected] > Created Time: Wed 04 Sep 2015 09:02:12 PM CST ************************************************************************/ #ifndef __BASE_SINGLETON_H__ #define __BASE_SINGLETON_H__ #include<new> #include "CMutex.h" template<typename T> class BaseSingleton { public: static T *Instance() { if(NULL != m_Instance) { return m_Instance; } m_Mutex.Lock(); if(NULL != m_Instance) { m_Mutex.UnLock(); return m_Instance; } m_Instance = new(std::nothrow) T(); m_Mutex.UnLock(); return m_Instance; } BaseSingleton(){} virtual ~BaseSingleton(){} private: static T *m_Instance; static CMutex m_Mutex; }; template<typename T> T *BaseSingleton<T>::m_Instance = NULL; template<typename T> CMutex BaseSingleton<T>::m_Mutex; #endif
測試用例:
TestSingleton.cpp
/************************************************************************* > File Name: TestSingleton.cpp > Author: KentZhang > Mail: [email protected] > Created Time: Wed 04 Sep 2015 09:21:10 PM CST ************************************************************************/ #include "BaseSingleton.h" #include <string> #include <iostream> class TestSingleton : public BaseSingleton<TestSingleton> { private: TestSingleton(){}; //建構函式,拷貝建構函式,宣告為私有,不允許在類外建立物件,保證該類只有一個物件 TestSingleton(const TestSingleton&){}; public: ~TestSingleton(){}; void Show(){std::cout<<"I am a singleton."<<std::endl;}; friend BaseSingleton<TestSingleton>; //由於建構函式為私有,而基類必須呼叫,所以這裡宣告基類為友元類 }; int main() { //TestSingleton ts; //這裡編譯報錯,顯然是不允許在類外建立物件 TestSingleton* p1 = TestSingleton::Instance(); p1->Show(); std::cout<<"p1="<<p1<<std::endl; //TestSingleton ts(*p1); //這種方式,同樣報錯 TestSingleton* p2 = TestSingleton::Instance(); p2->Show(); std::cout<<"p2="<<p2<<std::endl; TestSingleton* p3 = TestSingleton::Instance(); p3->Show(); std::cout<<"p3="<<p3<<std::endl; return 0; }
編譯:g++ CMutex.cpp TestSingleton.cpp -lpthread -o main
執行:./main
I am a singleton.
p1=0x82ad028
I am a singleton.
p2=0x82ad028
I am a singleton.
p3=0x82ad028
在本例中,有個明顯的缺陷,即那個靜態的單例指標才會何時delete,當然delete會自動呼叫它的解構函式完成終止化操作。
如果手動判斷delete,但是在大多時候,並不能準確的判斷單例何時不再使用,另一方面的單例類在記憶體中只有一個物件,
並不會造成記憶體洩露,因此大多數時候單例物件的析構是在程式結束的時候完成的。
上面的單例物件是在堆上分配的,需要手動delete,下面採用在靜態區分配物件,單例基類修改如下:
BaseSingleton.h
#ifndef __BASE_SINGLETON_H__
#define __BASE_SINGLETON_H__
#include<new>
#include "CMutex.h"
template<typename T>
class BaseSingleton
{
public:
static T *Instance()
{
if(NULL != m_Instance)
{
return m_Instance;
}
m_Mutex.Lock();
if(NULL != m_Instance)
{
m_Mutex.UnLock();
return m_Instance;
}
//m_Instance = new(std::nothrow) T();
static T tInstance; //這裡採用靜態區域性變數,保證程式執行時一直存在,程式結束時,會自動析構這個靜態變數
m_Instance = &tInstance;
m_Mutex.UnLock();
return m_Instance;
}
BaseSingleton(){}
virtual ~BaseSingleton(){}
static T *m_Instance;
static CMutex m_Mutex;
};
template<typename T>
T *BaseSingleton<T>::m_Instance = NULL;
template<typename T>
CMutex BaseSingleton<T>::m_Mutex;
#endif
由於筆者的水平有限,出錯在所難免,懇請讀者拍磚指正,謝謝閱讀。