C++单例模式的模板基类

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/KentZhang_/article/details/48206821
单例模式是很常用的设计模式,如果希望系统中某个类的对象只能有一个或者有一个就够了,那么便可以采用单例模式来解决。
下面用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

扫描二维码关注公众号,回复: 4007671 查看本文章

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


由于笔者的水平有限,出错在所难免,恳请读者拍砖指正,谢谢阅读

猜你喜欢

转载自blog.csdn.net/KentZhang_/article/details/48206821