面向对象设计与分析(28)单例模式的奇异递归模板CRTP实现

前面我们介绍了单例模式的两种实现:懒汉模式和饿汉模式,今天我们以新的方式来实现可复用的单例模式。

奇异递归模板是指父类是个模板类,模板类型是子类类型,即父类通过模板参数可以知道子类的类型。

// brief: a singleton base class offering an easy way to create singleton
#include <iostream>template<typename T>
class Singleton{
public:static T& Instance(){static T instance;return instance;}Singleton(const Singleton&)=delete;Singleton& operator =(const Singleton&)=delete;protected:Singleton() {std::cout<<"constructor called!"<<std::endl;}
};
/********************************************/
// Example:
// 1.friend class declaration is requiered!
// 2.constructor should be private
class DerivedSingle : public Singleton<DerivedSingle> {// !!!! attention!!!// needs to be friend in order to// access the private constructor/destructorfriend class Singleton<DerivedSingle>;private:DerivedSingle() = default;
};int main(int argc, char* argv[]){DerivedSingle& instance1 = DerivedSingle::Instance();DerivedSingle& instance2 = DerivedSingle::Instance();return 0;
}

该模式的思想是,通过模板类的静态成员变量来确保一个类只有一个实例,并且可以通过静态函数来获取该实例。在这种模式下,我们将 Singleton 类作为基类,派生出一个具体的单例类(例如 MySingleton),并让 MySingleton 类继承自 Singleton<MySingleton>

这个单例模式有非常多的实现细节需要注意,足以考察你的C++功底。

首先Singleton的构造是protected的,因为Singleton本身只是个帮助类,并没有单独实例化的需要,但是子类需要实例化,所以需要protected子类才可以访问。

Singleton 类中,我们定义了一个 Instance() 静态函数,返回一个类型为 T& 的对象。在 Instance() 函数中,我们定义了一个静态局部变量 instance,用于存储 T 类型的唯一实例。由于静态局部变量的生命周期与程序的运行周期相同,因此 nstance 只会在程序第一次调用 Instance() 函数时被创建,并在程序结束时被销毁。通过返回 instance 的引用,我们可以保证每次调用 Instance() 函数时都返回同一个实例。

此外,我们在 Singleton 类删除拷贝构造和赋值运算符的语句,以确保单例对象不能被复制或赋值,并且能够正确释放资源。

在这里基类的析构函数可以不需要 virtual ,因为子类在应用中只会用 Derived 类型,保证了析构时和构造时的类型一致

MySingleton 类中,我们只需要简单地继承自 Singleton<MySingleton>,并在构造函数中添加一些特定的逻辑即可。由于 MySingleton 类已经继承自 Singleton<MySingleton>,因此可以通过调用 Singleton<MySingleton>::Instance() 函数来获取唯一的 MySingleton 实例。

这种使用 CRTP 实现的单例模式具有以下优点:

  • 代码简洁:只需要定义一个基类和若干个派生类即可,无需编写大量重复的单例模式代码。
  • 线程安全:由于静态局部变量的创建是线程安全的,因此该模式天然支持多线程环境下的单例实现。
  • 性能高效:由于只需要在程序第一次调用 Instance() 函数时创建实例,因此该模式对性能的影响较小

这里也有几个特殊的限制:

  • 首先,子类还必须将构造私有化
  • 其次,由于子类构造私有化,但父类需要创建子类实例,因此需要将父类声明为子类的友元类。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/230421.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实验用python实现决策树和随机森林分类

1.实验目的 1.会用Python提供的sklearn库中的决策树算法对数据进行分类 2.会用Python提供的sklearn库中的随机森林算法对数据进行分类 3.会用Python提供的方法对数据进行预处理 2.设备与环境 使用Spyder并借助Python语言进行实现 3.实验原理 决策树( Decision Tree) 又称为…

【论文解读】Kvazaar 2.0: Fast and Efficient Open-Source HEVC Inter Encoder

时间&#xff1a;2020 级别&#xff1a;SCI 机构&#xff1a;Tampere University 摘要&#xff1a;高效视频编码(HEVC)是当前多媒体应用中经济的视频传输和存储的关键&#xff0c;但解决其固有的计算复杂性需要强大的视频编解码器实现。本文介绍了Kvazaar 2.0 HEVC编码器&…

RDD编程

目录 一、RDD编程基础 &#xff08;一&#xff09;RDD创建 &#xff08;二&#xff09;RDD操作 1、转换操作 2、行动操作 3、惰性机制 &#xff08;三&#xff09;持久化 &#xff08;四&#xff09;分区 &#xff08;五&#xff09;一个综合实例 二、键值对RDD &am…

SpringBoot + Vue前后端分离项目实战 || 三:Spring Boot后端与Vue前端连接

系列文章&#xff1a; SpringBoot Vue前后端分离项目实战 || 一&#xff1a;Vue前端设计 SpringBoot Vue前后端分离项目实战 || 二&#xff1a;Spring Boot后端与数据库连接 SpringBoot Vue前后端分离项目实战 || 三&#xff1a;Spring Boot后端与Vue前端连接 SpringBoot V…

【Python】—— Numpy 初体验

Numpy 初体验 第1关&#xff1a;Numpy 创建数组任务描述相关知识创建数组 编程要求测试说明运行代码 第2关&#xff1a;Numpy 数组的基本运算任务描述相关知识向量与向量之间1. 加法2. 减法3. 乘法&#xff08;X乘&#xff09;4. 乘法&#xff08;点乘&#xff09;5. 除法 向量…

【老牌期刊】IF:12,持续飙升,同领域期刊中的“佼佼者“,国人友好!

01 期刊概况 ARTIFICIAL INTELLIGENCE REVIEW ​ 【出版社】Springer 【ISSN】0269-2821 【EISSN】1573-7462 【检索情况】SCI&EI&Scopus在检 【WOS收录年份】1988年 【出刊频率】双月刊&#xff0c;最新一期December 2023 【期刊官网】 https://link.springe…

【Linux】进程周边005之环境变量

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.环境变量是什么&#xff1…

【视点合成】代码解读:生成demo视频

变换工具 def render_3dphoto(src_imgs, # 输入的源图像&#xff0c;维度为 [batch_size, 3, height, width]mpi_all_src, # 输入的所有源图像的MPI&#xff0c;维度为 [batch_size, num_planes, 4, height, width]disparity_all_src, # 所有源图像的视差信息&…

【Python】从文本中提取数字

使用以下正则表达式的下列模式用以提取文本中包含的数字&#xff1a; pattern r[^\-\d]*([-]?\d([.,]\d)?).*模式 1&#xff1a;正整数 text 123 result re.match(pattern, text) print(result[1]) # > 123text 123 result re.match(pattern, text) print(result[…

【博士论文写作 笔记01】绪论的写作

文章目录 1.1 研究背景与意义1.2 国内外研究现状1.3 主要研究内容1.4 本文组织架构 1.1 研究背景与意义 介绍本文研究的需求 行业现状&#xff1a;首先介绍一下课题涉及的行业是怎样的蓬勃发展。新问题&#xff1a;由于这种蓬勃发展带来了什么样的新问题。总结句&#xff1a;…

太阳能电池效能IV测试PV检测太阳光模拟器

目录 概述 一、系统组成 产品特点&#xff1a; 技术参数 数字源表 本系统支持Keithley24xx系列源表 标准太阳能电池 低阻测试夹具 自动化测试软件 概述 太阳能光伏器件的所有性能表征手段中&#xff0c;IV特性测试无疑是最直观、最有效、最被广泛应用的一种…

【OS】操作系统总复习笔记

操作系统总复习 文章目录 操作系统总复习一、考试题型1. 论述分析题2. 计算题3. 应用题 二、操作系统引论&#xff08;第1章&#xff09;2.1 操作系统的发展过程2.2 操作系统定义2.3 操作系统的基本特性2.3.1 并发2.3.2 共享2.3.3 虚拟2.3.4 异步 2.4 OS的功能2.5 OS结构2.5 习…

Android studio 按键控制虚拟LED

一、activity_main.xml代码&#xff1a; <?xml version"1.0" encoding"utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.a…

《Linux C编程实战》笔记:进程操作之创建进程

进程是一个动态的实体&#xff0c;是程序的一次执行过程。进程是操作系统资源分配的基本单位。 以下是一些概念&#xff0c;我就直接抄书了 进程是操作系统的知识&#xff0c;简单理解的话&#xff0c;你写的代码运行起来算一个进程&#xff1f; 创建进程 每个进程由进程ID号…

GPT-4.5!!!

GPT-4 还没用明白&#xff0c;GPT-4.5 就要发布了。 最近&#xff0c;OpenAI 泄露了 GPT-4.5 的发布页面&#xff0c;除了进一步增强复杂推理和跨模态理解&#xff0c;GPT-4.5 增加了一个更加强大的功能——3D。 3D 功能的进一步支持&#xff0c;也就意味着多模态最后一块版图…

工作中git工具分支和主干合并

克隆下载一个现有的 Git 仓库到本地 git clone ssh仓库地址下载后查看工作区状态包括哪些文件被修改、新增或删除等。 git status在本地建立我自己的分支&#xff08;取名Bms-Dev&#xff09;或者切换到指定的分支&#xff0c;才能提交到远程仓库上Bms-Dev的分支 git checko…

关于前端学习的思考-浮动元素嵌套块级元素12.18

1、块级元素嵌套浮动元素 先摆图片&#xff0c;当橘色的盒子高度减少的时候&#xff0c;NK AD TB PK NN并不会减少。如何解决呢&#xff1f; 加一个overflow&#xff1a;clip或者hidden 2、浮动元素嵌套块级元素 加一个overflow&#xff1a;clip或者hidden 综上所述&#xff0…

giee 添加公匙 流程记录

一、安装 百度网盘CSDN4文件夹下&#xff0c;或者官网下载&#xff1a;https://git-scm.com/downloads 二、生成密钥 1.右击打开git bash 2.$ ssh-keygen -t rsa -C “个人邮箱地址”&#xff0c;按3个回车&#xff0c;密码为空。 3.在C:\Users{windows用户名}.ssh目录下得到…

[Ray Tracing in One Weekend] 笔记

前言 本文参照自raytracing in one weekend教程&#xff0c;地址为&#xff1a;https://raytracing.github.io/books/RayTracingInOneWeekend.html 什么是光线追踪&#xff1f; 光线追踪模拟现实中的成像原理&#xff0c;通过模拟一条条直线在场景内反射折射&#xff0c;最终…

Poco SendHttpRequest PocoServer 2021-03-31

PocoServer // PocoHttpServer.cpp : 定义控制台应用程序的入口点。 //#include "stdafx.h" #include <Poco/Net/HTTPRequestHandler.h> #include <Poco/Net/HTTPRequestHandlerFactory.h> #include <Poco/Net/HTTPServerRequest.h> #include <…