在实现单例类时,通常要把构造相关的几个函数访问权限设为private或protected(最好是private)。但假设一个大型系统中,有数十个单例类(这很正常,单例类其实是外观模式的一种最常用设计),每一个都这么写显得繁琐不堪。要把这些操作代表的代码复用,可以使用c++语言提供的利器---继承。

设计如下的基类:

 class NonCopyable {
public:
NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
void operator=(const NonCopyable& c) = delete;
};

当单例类继承此类后,客户就无法在复制或赋值此单例类的实例化对象了,这样整个内存只存在一个全局对象。这里的NonCopyable类实现参考了boost::noncopyable。

解决了构造函数访问权限问题后,还有个问题,就是如何实例化?单例类实现的经典做法是在类里声明一个私有的静态类对象的指针,使用get手法返回此对象实例引用,通过此引用再调用类的其它方法。很好,但每个单例类都要这么实现一遍仍然繁琐。此时可以使用C++提供的另一个代码复用的利器--template。先实现一个通用的singleton模板类,模板类型参数传入待实现的单例类名,这样在编译阶段就完成了单例类的构造(模板实例化)。

通用的singleton模板类实现如下:

 template <class T>
class Singleton : public NonCopyable {
private:
static T* inst_; public:
Singleton() {}
virtual ~Singleton() {} static T& inst()
{
if (!inst_) inst_ = new T;
return *inst_;
} static void uninst()
{
if (!inst_) return;
delete inst_;
inst_ = nullptr;
} };
//__declspec(selectany)声明使得我们可以在头文件中初始化一个全局变量
template <class T> __declspec(selectany) T * Singleton<T>::inst_ = nullptr;

自定义单例类实现:

 class singletontest :public Singleton<singletontest>
{
public:
singletontest(){ printf("singletontest constructor function called "); }
~singletontest(){ printf("class test object destroyed "); }
//成员方法
void print(){
printf("singletontest::print function called ");
}
};

测试代码:

 singletontest::inst().print(); //line1
singletontest a; //line 2 无法阻止默认构造,理想中,单例类只允许出现类似line1的调用
printf("singletontest obj a addr is %d\n", &a);
a.print();
singletontest b;
printf("singletontest obj b addr is %d\n", &b);
b.print();
//a(b); //singletontest继承了noncopyable,继承类初始化时先调用父类的构造函数,由于定义成私有,所以构造失败
//a = b; //同上,赋值运算操作符函数同样是私有的

测试结果:

line2行代码写完后编译期并不报错,意味着对象使用默认构造生成。想阻止这种行为,就要把默认构造函数设为私有,但inst()方法里的 new T就会失败,更加得不偿失。

测试 line 8、9代码的错误,编译器可以识别。

代码里存在三层的继承链(singletontest-> singleton<T>-> Noncopyable),但因为类中没有声明虚函数,调用方法上无周转之处,所以性能上没有任何损失。

singletontest:public sington<singletontest>这种写法成文CRTP(Curiously Recurring Template Pattern:奇异递归模板模式),常用于实现静多态,本文不作过多介绍。

最后,一般在多线程环境中讨论单例类创建时,常有饱汉式与饿汉式两种方式,但现代C++已经保证了静态成员变量创建的线程安全性,所以再无讨论这种方式的必要了

当noncopyable遇见singleton的更多相关文章

  1. item2,实现singleton模式

    单例模式? 只能实现一个实例的类成为单例. ============== muduo库中单例模式实现 #include<boost/noncopyable.hpp> //#include ...

  2. pthread_once重塑singleton模式

    单件模式是非线程安全的: // Single threaded version class Foo { private Helper helper = null; public Helper getH ...

  3. boost::singleton

    singleton即单件模式,实现这种模式的类在程序生命周期里只能有且仅有一个实例. 使用singleton,需要包括头文件: #include <boost/serialization/sin ...

  4. Be Better:遇见更好的自己-2016年记

    其实并不能找到好的词语来形容过去的一年,感觉就如此平淡的过了!没有了毕业的稚气,看事情淡了,少了一丝浮躁,多了一分认真.2016也许就是那句话-多读书,多看报,少吃零食多睡觉,而我更愿意说--Be B ...

  5. 23种设计模式--单例模式-Singleton

    一.单例模式的介绍 单例模式简单说就是掌握系统的至高点,在程序中只实例化一次,这样就是单例模式,在系统比如说你是该系统的登录的第多少人,还有数据库的连接池等地方会使用,单例模式是最简单,最常用的模式之 ...

  6. 设计模式之单例模式(Singleton)

    设计模式之单例模式(Singleton) 设计模式是前辈的一些经验总结之后的精髓,学习设计模式可以针对不同的问题给出更加优雅的解答 单例模式可分为俩种:懒汉模式和饿汉模式.俩种模式分别有不同的优势和缺 ...

  7. PHP设计模式(四)单例模式(Singleton For PHP)

    今天讲单例设计模式,这种设计模式和工厂模式一样,用的非常非常多,同时单例模式比较容易的一种设计模式. 一.什么是单例设计模式 单例模式,也叫单子模式,是一种常用的软件设计模式.在应用这个模式时,单例对 ...

  8. 自建git node pm2 (不赘述,就说遇见的问题)

    //======================[git]部分 主题部分还是按照网上的办法进行安装. 安装的话  分为两个办法(一个是yum (contos办法)  或者sudo(ubuntu办法) ...

  9. The Java Enum: A Singleton Pattern [reproduced]

    The singleton pattern restricts the instantiation of a class to one object. In Java, to enforce this ...

随机推荐

  1. qrcode生成二维码

    代码: <!DOCTYPE html> <html lang="en" style="height: 99%"> <head> ...

  2. C#进阶系列——AOP

    一.AOP概念(转自) 老规矩,还是先看官方解释:AOP(Aspect-Oriented Programming,面向切面的编程),它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程 ...

  3. leetcode55

    bool canJump(vector<int>& nums) { ]; ; i < nums.size() && reach >= i; i++) { ...

  4. __enter__ 和 __exit__上下文管理协议

    class F: def __init__(self,n): self.n = n def __enter__(self): print('执行enter') return self def __ex ...

  5. kill all java php rm.sh

    #!/bin/sh#根据进程名杀死进程#FileName: killjavaphprm.sh #查看php进程IDecho "php进程ID:"pgrep php #杀死所有php ...

  6. Mask RCNN 源码阅读(update)

    之前看了Google官网的object_dectect 的源码,感觉Google大神写的还不错.最近想玩下Mask RCNN,就看了下源码,这里刚好当做总结和梳理.链接如下: Google官网的obj ...

  7. ntp时间同步参考

    https://blog.csdn.net/kamereon/article/details/54344114

  8. 【javascript知识温习】设计模式--单例模式

    var Singleton = (function(){ var instance; function init() { '; function privateMethod() { console.l ...

  9. EOS.IO Technical White Paper v2

    [EOS.IO Technical White Paper v2] Abstract: The EOS.IO software introduces a new blockchain architec ...

  10. java集合: jdk1.8的hashMap原理简单理解

    HashMap的数据结构 HashMap是数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的,他的底层结构是一个数组,而数组的元素是一个单向链表.HashMap默认初始化的是一个长度为16位的数 ...