0
点赞
收藏
分享

微信扫一扫

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


文章目录

  • ​​1.用模板实现单例模式​​
  • ​​2.第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章的动态创建对象改为用模板方式来实现

  • eg:P71\02下面的所有文件
  • 测试:
  • (P71)模板四:用模板实现单例模式,第36章的动态创建对象改为用模板方式来实现_搜索引擎

  • 参考:从零开始学C++之模板(四):用模板实现单例模式(线程安全)、模板方式实现动态创建对象


举报

相关推荐

0 条评论