(P71)模板四:用模板实现单例模式,第36章的动态创建对象改为用模板方式来实现

1.用模板实现单例模式

  • eg:
    P71\Singleton.h
#ifndef _SINGLETON_H
#define _SINGLETON_H

#include <cstdlib>
#include <iostream>
using namespace std;

//将Singleton类模板看成是单例模式类的包装器,用它可以产生单例模式类
//GetInstance返回的不是Singleton自身,而是它所包装的对象T
template <typename T>
class Singleton
{
public:
	//方法1:
	// static T& GetInstance()//返回的是引用,所以不会调用拷贝构造函数
	// {
	// 	static T instance;		// 局部静态对象:是在运行期初始化,是有状态的
	// 	return instance;				//第2次调用时,会返回先前所初始化的实例,以此来保证单例
	// }

	//方法2:
	//静态成员函数不能调用非静态函数
	static T& GetInstance()
	{
		// pthread_once(Init());//多个线程访问GetInstance时,Init只是调用一次,(3)linux底下推荐使用pthread_once
		Init();
		return *instance_;
	}

	/*
	static T& GetInstance()这种并不是线程安全的,原因如下:
	因为2个线程可能同时调用了GetInstance,2个线程同时进行了if (instance_ == 0)判断,会new2个对象,此时不是线程安全的。
	解决办法:
	(1)普通锁,不推荐
	(2)double check lock双检测锁,不推荐
	(3)linux底下推荐使用pthread_once
	*/


private:
	static void Init()
	{
		// lock();(1)普通锁
		if (instance_ == 0)
		{
			// //再检测一次
			// lock();(2)double check lock双检测锁
			// if (instance_ == 0)
			// ulock();(2)double check lock双检测锁
			instance_ =new T;
			//将Destroy函数注册进去,程序结束时,会调用注册的函数(可以注册多个,后注册的函数先调用)
			//仅仅注册一次
			atexit(Destroy);//单例模式对象销毁推荐使用的方式,而不要使用智能指针
		}
		// ulock();//(1)普通锁
	}
	static void Destroy()
	{
		delete instance_;
	}

	Singleton(const Singleton& other);
	Singleton& operator=(const Singleton& other);
	Singleton();
	~Singleton();

	static T* instance_;
};

template <typename T>
T* Singleton<typename T>::instance_ = 0;//初始化为空指针

#endif //_SINGLETON_H

P71\01.cpp

#include <iotream>
using namespace std;
#include "Singleton.h"


//希望ApplicationImpl类变成单例模式,可以使用模板方式来实现单例模式
class ApplicationImpl
{
public:
    ApplicationImpl() {cout<<"ApplicationImpl ..."<<endl;}
    ~ApplicationImpl() {cout<<"~ApplicationImpl" ...<<endl;}
    void Run() {cout<<"Run ..."<<endl;}
};

//将Singleton类模板看成是单例模式类的包装器,用它可以产生单例模式类
//Application是一个单例模式类,不能构造对象
typedef Singleton<ApplicationImpl> Application;

int main(void)
{
    // Application a;//Application是一个单例模式类,不能构造对象

    Application::GetInstance().Run();
    Application::GetInstance().Run();

	return 0;
}
  • 测试:
    两次获取对象,只构造一次,只析构一次,说明获取的是同一个对象。
    同一个对象的Run()方法可以调用多次。
    在这里插入图片描述

2.第36章的动态创建对象改为用模板方式来实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喜欢打篮球的普通人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值