C++ 单例模式 模版类(Meyers‘ Singleton)
自己实现的Meyers’ Singleton的单例模式模板类。
1 不继承
具体类无需继承, 使用Singleton<Test>::getInstance()获得唯一实例。
template<typename T>
class Singleton
{private:Singleton() = default; // 设置为私有(protected也行),禁止外部直接构造public:Singleton(const Singleton&) = delete; // 禁止拷贝构造Singleton& operator = (const Singleton&) = delete; // 禁止拷贝赋值~Singleton() = default;public:static T& getInstance() // Meyers' Singleton {static T instance;return instance;}
};class Test
{public:Test() = default;~Test() = default;public:void Func() { std::cout << "Test::Func()" << std::endl; }
};#define TestInstance Singleton<Test>::getInstance() // 这里注意没有分号
调用如下:
int main()
{TestInstance.Func();return 0;
}
这种实现方式简单、方便,无需继承。
由于无需继承,通过Test类声明无法知道该类为单例类,意义不明确。
由于Singleton中需要调用Test的构造函数,所以必须将其声明为public。这会导致无法阻止外部直接构造Test对象。
2 继承
template<typename T>
class Singleton
{public:~Singleton() = default;static T& getInstance() // Meyers' Singleton { static T instance;return instance;}private:Singleton(const Singleton&) = delete; // 禁止拷贝构造Singleton& operator = (const Singleton&) = delete; // 禁止拷贝赋值protected: // 允许被继承类调用Singleton() = default; // 设置为私有,禁止外部直接构造
};class Test : public Singleton<Test>
{public:void Func() { std::cout << "Test::Func()" << std::endl; }public: // 只能为public,否则编译报错,不能阻止外部调用Test() = default;
};#define TestInstance Test::getInstance()
Test继承Singleton,通过类声明就知道Test是个单例类。但是构造函数依然只能声明为public,导致外部依旧能直接调用构造Test对象。
3 继承+友元
template<typename T>
class Singleton
{public:friend typename T; // 友元声明public:~Singleton() = default;static T& getInstance() // Meyers' Singleton { static T instance;return instance;}private:Singleton(const Singleton&) = delete; // 禁止拷贝构造Singleton& operator = (const Singleton&) = delete; // 禁止拷贝赋值private:Singleton() = default; // 设置为私有,禁止外部直接构造
};class Test : public Singleton<Test>
{public:friend class Singleton<Test>; // 友元声明public:void Func() { std::cout << "Test::Func()" << std::endl; }private: // 构造函数可以声明为private,阻止外部直接调用Test() = default;
};#define TestInstance Test::getInstance()
通过相互声明为友元,Test的构造函数即使声明为private,Singleton的依旧能访问其构造函数,不会编译报错。
同时private阻止外部直接构造Test对象,只能通过Test::getInstance()获取唯一实例。当然,这就要求新类继承自Singleton时必须将Singleton声明自己的友元类。
4 继承+友元(小改版)
template<typename T>
class Singleton
{protected: // 不能直接构造,同时子类可访问,这是protected的优势Singleton() = default;public: // 不提供拷贝构造函数和赋值函数Singleton(const Singleton& one) = delete;Singleton& operator=(const Singleton& one) = delete;public: // 全局访问函数static T& GetInstance(){static T instance;return instance;}
};class Test : public Singleton<Test> // 继承自Singleton<TestClass>
{public: // 必须提供friend Singleton<Test>;private: // 不能直接构造,也可使用protectedTest() = default;public:void TestFunc(){}
};
当Test继承子Singleton<Test>后,需要改动的地方有两处:
- 声明Singleton<Test>为友元。
- 声明构造函数为private或者protected。
感觉还是比较麻烦,想最终实现的功能是:一个类想要变成单例类,只需要继承自单例模板类即可,无需再做其他修改。
C++ 单例模式 模版类(Meyers‘ Singleton)相关推荐
- spring入门(11)-spring与hibernate整合完成增删改查的操作(封装HibernateTemplate模版类对象)
今天是spring的最后一节课,这节课老师讲了spring与hibernate整合完成增删改查的操作,这是很重要的一节课,这也是第一次真正的实现spring结合Hibernate和数据库连接上,下面是 ...
- 快速排序和选择模版类
快速排序和选择模版类 template<typename T> void insert_sort(T *array,int start,int end) {for (int i = sta ...
- C++工作笔记-模版类要注意的地方(对比模版函数)
指定了模版参数类型后,在编译的时候就会生成一个新的具体的类,然后用这个类构造对象.用<>来指定模版的类型 而函数模版就不是这样,他先调用函数,发现是什么类型再推到,而类是必须要指定的 所有 ...
- C++普通类继承模版类demo
1.定义并继承一个模版类 template<typename T> class Test : public T{ } 2.继承一个模版类 class Subtest : ...
- C++模版类List实现
模版类即使用模版的泛型方式来编写类似链表的链式物理结构,这篇文章我是以动态数组的方式实现的,所以是List线性物理结构! 1.包含头文件 定义函数执行的正确与错误宏用来判断函数执行,其次在定义类型别名 ...
- 泛型模版类出现了LNK2019: 无法解析的外部符号错误
我们在写程序的大部分时间都不会去考虑在已有的知识上出现的匮乏,前两天用C++写了一个顺序表,结果却不尽人意,这个或许是因为人生就是这样,在你已知的知识当中出现的知识漏洞你会很难发现,这里还是感谢一下s ...
- python采用单例模式游戏_Python实现Singleton模式的方式详解
前言 使用python实现设计模式中的单例模式.单例模式是一种比较常用的设计模式,其实现和使用场景判定都是相对容易的.本文将简要介绍一下python中实现单例模式的几种常见方式和原理.一方面可以加深对 ...
- Python实现单例模式常量类
import osclass Singleton:"""单例模式"""def __new__(cls, *args, **kwargs):i ...
- 单例模式——一个类只有一个实例
目录 一.基础简介 1.定义 2.使用场景 3.优缺点 4.模式分析 二.代码实现 1.sington类 2.代码分析 一.基础简介 1.定义 保证一个类仅有一个实例,并提供一个全局访问点 2.使用场 ...
- 一个简单的单例模式的类
public class Singleton {private Singleton(){}private static Singleton instance;public static Singlet ...
最新文章
- 【django】如何搭建虚拟环境(解决mkvirtualenv:未找到命令)
- Dojo 之 面向对象
- twitter storm源码走读(二)
- HTML入门学习 -- HTML基础知识
- STM32F103_DDWG窗口看门狗
- Linux 4.16 正式发布:不再支持 8 种 CPU 架构,内核减少了 450000 行代码 !
- The VMRC console has disconnected solution
- dqkg的命令用法_CADk中常用命令使用方法及说明
- C10K 和 C1000K 回顾
- EasyDarwin流媒体云平台:EasyCamera开源摄像机接入海康威视摄像机实时视频
- 2017软件测试考试分值,2017年英语四级分值分配「最新」
- 敏捷开发的价值观与十二条原则
- 漫谈 | 据说搞区块链的人都觉得自己是“上帝
- 组装一台计算机需要哪些硬件(写出配置),电脑组装知识网组装电脑配置单中都有哪些配置组装电脑需要的电脑硬件...
- 新电脑win10系统的一个BUG
- 什么是RS485总线?
- 经济学家―狗屎―GDP
- C++基础入门丨1. 初识C++像极了C语言
- Cisco ASA 5585 with firepower upgrade 升级 配置证书
- linux 车载导航源代码,基于Linux的嵌入式车载导航系统的设计