原文链接:C++单例模式的模板基类
发布时间:2015-09-04 09:35:52
单例模式是很常用的设计模式,如果希望系统中某个类的对象只能有一个或者有一个就够了,那么便可以采用单例模式来解决。
下面用C++实现一个单例模板类,那么其他的类只需继承它,便可以成为单例类。
本例中使用了 CMutex类,是考虑多线程的情况,这个类的定义请参见笔者的另一篇博客《C++简单封装互斥量》,
链接 http://blog.kentonly.com/2015/09/02/2015-09-02-C++简单封装互斥量/
代码如下:
BaseSingleton.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
#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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
#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* p1 = TestSingleton::Instance(); p1->Show(); std::cout<<"p1="<<p1<<std::endl;
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
1 2 3 4 5 6 7 8 9 10 11
| I am a singleton.
p1=0x82ad028
I am a singleton.
p2=0x82ad028
I am a singleton.
p3=0x82ad028
|
在本例中,有个明显的缺陷,即那个静态的单例指针才会何时delete,当然delete会自动调用它的析构函数完成终止化操作。
如果手动判断delete,但是在大多时候,并不能准确的判断单例何时不再使用,另一方面的单例类在内存中只有一个对象,
并不会造成内存泄露,因此大多数时候单例对象的析构是在程序结束的时候完成的。
上面的单例对象是在堆上分配的,需要手动delete,下面采用在静态区分配对象,单例基类修改如下:
BaseSingleton.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #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; }
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
|
由于笔者的水平有限,出错在所难免,恳请读者拍砖指正,谢谢阅读。