当noncopyable遇见singleton
在实现单例类时,通常要把构造相关的几个函数访问权限设为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的更多相关文章
- item2,实现singleton模式
单例模式? 只能实现一个实例的类成为单例. ============== muduo库中单例模式实现 #include<boost/noncopyable.hpp> //#include ...
- pthread_once重塑singleton模式
单件模式是非线程安全的: // Single threaded version class Foo { private Helper helper = null; public Helper getH ...
- boost::singleton
singleton即单件模式,实现这种模式的类在程序生命周期里只能有且仅有一个实例. 使用singleton,需要包括头文件: #include <boost/serialization/sin ...
- Be Better:遇见更好的自己-2016年记
其实并不能找到好的词语来形容过去的一年,感觉就如此平淡的过了!没有了毕业的稚气,看事情淡了,少了一丝浮躁,多了一分认真.2016也许就是那句话-多读书,多看报,少吃零食多睡觉,而我更愿意说--Be B ...
- 23种设计模式--单例模式-Singleton
一.单例模式的介绍 单例模式简单说就是掌握系统的至高点,在程序中只实例化一次,这样就是单例模式,在系统比如说你是该系统的登录的第多少人,还有数据库的连接池等地方会使用,单例模式是最简单,最常用的模式之 ...
- 设计模式之单例模式(Singleton)
设计模式之单例模式(Singleton) 设计模式是前辈的一些经验总结之后的精髓,学习设计模式可以针对不同的问题给出更加优雅的解答 单例模式可分为俩种:懒汉模式和饿汉模式.俩种模式分别有不同的优势和缺 ...
- PHP设计模式(四)单例模式(Singleton For PHP)
今天讲单例设计模式,这种设计模式和工厂模式一样,用的非常非常多,同时单例模式比较容易的一种设计模式. 一.什么是单例设计模式 单例模式,也叫单子模式,是一种常用的软件设计模式.在应用这个模式时,单例对 ...
- 自建git node pm2 (不赘述,就说遇见的问题)
//======================[git]部分 主题部分还是按照网上的办法进行安装. 安装的话 分为两个办法(一个是yum (contos办法) 或者sudo(ubuntu办法) ...
- The Java Enum: A Singleton Pattern [reproduced]
The singleton pattern restricts the instantiation of a class to one object. In Java, to enforce this ...
随机推荐
- 日志模块logging
import logging # 设置日志基础样式 logging.basicConfig(level=logging.INFO, format='levelname:%(levelname)s fi ...
- 杰克.多西 twitter创始人 必做清单和不必做清单
必做清单 活在当下 接受脆弱(Be vulnerable) 只喝柠檬水和红酒 每天 6 组下蹲和俯卧撑 每天跑步 3 英里 每天思考本清单 站直了 打拳击沙袋 10 分钟 跟所有人打招呼 每天 7 小 ...
- Android向系统日历中添加日程事件
转自Android向系统日历中添加日程事件 总结 在项目开发中,我们有预约提醒.定时提醒需求时,可以使用系统日历来辅助提醒: 通过向系统日历中写入事件.设置提醒方式(闹钟),实现到时间自动提醒的功能: ...
- 《从零玩转python+人工智能-3》网易云课堂王顺子
#1.145——152节课25章——面向对象三大特性小案例 class Animal: def __init__(self,name,age=1): self.name = name self.age ...
- JPA中建立数据库表和实体间映射小结
在JPA中,映射数据库表和实体的时候,需要注意一些细节如下, 实体类要用@Entity的注解: 要用 @Id 来注解一个主键: 如果跟数据库相关联,要用@Table注解相关数据库表: 实体类中字段需要 ...
- ReactiveX 学习笔记(24)使用 RxCpp + C++ REST SDK 调用 REST API
JSON : Placeholder JSON : Placeholder (https://jsonplaceholder.typicode.com/) 是一个用于测试的 REST API 网站. ...
- LevelDB源码分析-sstable的Block
sstable中的Block(table/block.h table/block.cc table/block_builder.h table/block_builder.cc) sstable中的b ...
- [C语言]进阶|图形库
---------------------------------------------------------------------- // main.c // Created by weich ...
- JAVA条件判断
一.基本if结构 1.流程图 l 输入输出 l 判断和分支 l 流程线 1.1 简单的if条件判断 if(表达式){ //表达式为true,执行{ ...
- EOS keosd
[EOS keosd] The program keosd, located in the eos/build/programs/keosd folder within the EOSIO/eos r ...