当前位置: 首页 > news >正文

C++特殊类设计(单例模式等)

目录

引言

1.请设计一个类,不能被拷贝

2. 请设计一个类,只能在堆上创建对象

为什么设置实例的方法为静态成员呢

3. 请设计一个类,只能在栈上创建对象

4. 请设计一个类,不能被继承

5. 请设计一个类,只能创建一个对象(单例模式)

饿汉模式

懒汉模式

单例对象一般不考虑析构

为什么私有析构呢?


引言

在当今的软件开发实践中,特殊类设计模式扮演着至关重要的角色,它们不仅提高了代码的可维护性和可扩展性,还确保了系统的稳定性和性能。其中,单例模式作为最常用的设计模式之一,以其独特的实例管理方式,成为了许多场景下的首选解决方案。本文旨在探讨C++中单例模式及其他特殊类设计的精髓,通过分析其背后的设计哲学和实现技巧,帮助读者掌握这些高级编程技巧,以提升其在软件开发过程中的设计能力和代码质量。

在我们设计一个特殊类的时候,一般要把构造、拷贝和赋值私有保护,防止被其他类拷贝或者产生不想要(意料之外)的错误。

1.请设计一个类,不能被拷贝

拷贝只会放生在两个场景中:拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝,

只需让该类不能调用拷贝构造函数以及赋值运算符重载即可
C++98
将拷贝构造函数与赋值运算符重载只声明不定义,并且将其访问权限设置为私有即可。
class CopyBan
{// ...private:CopyBan(const CopyBan&);CopyBan& operator=(const CopyBan&);//...
};

C++11

C++11扩展delete的用法,delete除了释放new申请的资源外,如果在默认成员函数后跟上
=delete,表示让编译器删除掉该默认成员函数。
class CopyBan
{// ...CopyBan(const CopyBan&)=delete;CopyBan& operator=(const CopyBan&)=delete;//...
};

同时我们还可以设置一个基类,让子类继承基类,让子类正常实现功能,设置基类不可被拷贝即可。

2. 请设计一个类,只能在堆上创建对象

实现方式:
1. 将类的构造函数私有,拷贝构造声明成私有。防止别人调用拷贝在栈上生成对象。
2. 提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建。
只能在堆上创建对象,即只能new对象,不允许在栈上创建临时变量。当然要禁用拷贝、构造、赋值函数(非单例)
class HeapOnly    
{     
public:     static HeapOnly* CreateObject()  {      return new HeapOnly;    }
private:    HeapOnly() {}// C++98// 1.只声明,不实现。因为实现可能会很麻烦,而你本身不需要// 2.声明成私有HeapOnly(const HeapOnly&);// or// C++11    HeapOnly(const HeapOnly&) = delete;
}

由于没有this指针,无法调用构造,而是只是去new这个镀锡,由系统去完成资源的申请


静态不能调用非静态就是因为没有this指针,缺少调用的参数

但是new和delete这种操作不需要this指针

那每次调的时候,返回的都是一个新的静态对象吗?--- NO!这个方法是静态的,但是返回的变量不是静态的

为什么设置实例的方法为静态成员呢

收线确定的是,一定是内部new创建的对象。

因为如果设置为非静态成员,那就只能通过对象去调用,但是我们不能去在栈区创建对象。

并且构造私有,外部一定不可以创建对象,只能用类调用,所以必须静态!

为什么禁用拷贝构造:比如A a1(a2);这样a1依然是在栈区!

3. 请设计一个类,只能在栈上创建对象

只能通过类型创建,禁止new对象

方法一:同上将构造函数私有化,然后设计静态方法创建对象返回即可
依然需要把构造私有,需要注意的是,不能把构造和拷贝工构造私有
class StackOnly
{
public:static StackOnly CreateObj(){StackOnly obj;return obj;}void* operator new(size_t size) = delete;void operator delete(void* p) = delete;
private:StackOnly()  :_a(0){}
private:int _a;
};

1.设置为静态:

并且构造私有,外部一定不可以创建对象,只能用类调用,所以必须静态!

2.为什么不可以禁用拷贝构造:比如A a1(a2);这样a1依然是在栈区!符合要求,并且匿名对象的声明周期只在这一行!为了防止匿名对象周期太短,无法进行较好的连续性开发,所以需要赋值给另一个栈区的对象。

3.可以返回临时对象,只需要赋值给其他对象即可(栈区);也可以返回非匿名对象,也是采用赋值的方式进行连续性开发。

4.为了防止创建堆区对象,需要禁用new和delete(为了防止创建栈区对象时,需要禁用拷贝、赋值)

        

4. 请设计一个类,不能被继承

C++98方式

// C++98中构造函数私有化,派生类中调不到基类的构造函数。则无法继承
class NonInherit
{
public:static NonInherit GetInstance(){return NonInherit();}
private:NonInherit(){}
};
C++11方法
final关键字, final修饰类,表示该类不能被继承。
class A  final
{// ....
};

5. 请设计一个类,只能创建一个对象(单例模式)

设计模式:
设计模式(Design Pattern)是一套 被反复使用、多数人知晓的、经过分类的、代码设计经验的
总结。为什么会产生设计模式这样的东西呢?就像人类历史发展会产生兵法。最开始部落之间打
仗时都是人拼人的对砍。后来春秋战国时期,七国之间经常打仗,就发现打仗也是有 套路的,后
来孙子就总结出了《孙子兵法》。孙子兵法也是类似。
使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模
式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。
单例模式:
一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个
访问它的全局访问点,该实例被所有程序模块共享。比如在某个服务器程序中,该服务器的配置
信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再
通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。
单例模式有两种实现模式:

饿汉模式

饿汉模式:已经饿得不行了,要求立刻有东西吃,即在main函数之前就得创建好---全局

饿汉:设置为全局,提前创建。

既然是单例,一定先把构造私有。

在类的外部虽然不能创建全局的对象,但是在类的内部可以创建。----思路:类的内部声明静态成员,类的外部定义,这样就是一个全局的数据。

demo
// 懒汉模式:第一次用的时候再创建(现吃现做)
class A {
public:static A* GetInstance() {return _inst;}
private:A() {}map<string, string> _dict;int _n = 0;static A* _inst;
};

我们在类的内部创建对象的时候,当然不能

   class        A

        A   _a;

  }

这样属于嵌套定义。
但是也不能内部用静态成员方法去获取,因为函数需要在主函数内调用。
当我们在内部使用静态成员的时候,当然不是嵌套定义,因为静态不属于某个对象,而是属于整个类。并且,我们只能是在类内声明,并没有定义,需要在类的外部定义。
在类的外部定义的时候,只需要点名:类型 + 作用域即可,不需要再次声明静态,静态只需要声明一次即可,但是定义(实例化),必须使用类型。
当需要使用这个实例的时候,调用实例方法去获取即可。
总结:
1.类内声明静态,类外实例化静态(全局)
2.类内提供获取实例的犯法
同时删除拷贝构造和赋值

访问成员需要借助对象,这时候就需要调用GetInstance函数

优点:创建简单 

缺点:1.进程启动慢

           2.一旦存在两个全局单例,不能控制单例启动的先后顺序。

懒汉模式

现吃现做,不着急,main函数内创建。

  只需要把静态的对象换成指针即可,获取实例的时候,如果指针是nullptr,那么创建,如果不是,那么直接返回

线程不安全,两个线程同时进来,可能会new两个对象---加锁

单例对象一般不考虑析构

恶汉不存在释放的问题--全局,

懒汉对象也一般不需要释放---单例对象一般是生命周期伴随整个程序,对整个程序都起到至关重要的作用,进程结束时,会自动释放。

就算要释放,如果我们期望既可以手动释放(析构不能手动释放),也可以在main函数结束时自动释放

class B
{
public:static B* GetInstance(){if (_inst == nullptr){_inst = new B;}return _inst;}static void DelInstance(){if (_inst){delete _inst;_inst = nullptr;}}private:B(){}~B(){// 持久化:要求把数据写到文件cout << "数据写到文件" << endl;}B(const B& aa) = delete;B& operator=(const B& aa) = delete;map<string, string> _dict;int _n = 0;static B* _inst;class gc{public:~gc(){DelInstance();}};static gc _gc;
};B* B::_inst = nullptr;
B::gc B::_gc;

可以私有析构函数

提供一个调用析构函数的接口DelInstance,我们可以手动调用这个接口去进行析构。

我们新建一个内部类,这个内部类是外部类的友元,可以访问私有。等main函数结束的时候_gc调用析构,析构会调用DelInstance。

这样可以做到:1.显示释放(析构不允许显示调用,但是delete指针的时候,可以调用析构)

                        2.没有显示释放,等程序结束也会释放

为什么私有析构呢?

B* instance = B::GetInstance();
delete instance;

B* instance2 = B::GetInstance();

如果是public的话,每个人可以自己delete这个,那么就违背单例模式的原则了!

而这块放的这个DelInstance函数是意思万一情况下,不使用单例了,自己想释放的话,可以通过这个函数释放,但是一般也不会这样做的,一般gc就替咱们回收了

总之就是:不能让其他人去随便delete单例,所以私有;同时希望gc能够管理单例,等程序结束,gc清理的时候,gc会协助清理单例

相关文章:

C++特殊类设计(单例模式等)

目录 引言 1.请设计一个类&#xff0c;不能被拷贝 2. 请设计一个类&#xff0c;只能在堆上创建对象 为什么设置实例的方法为静态成员呢 3. 请设计一个类&#xff0c;只能在栈上创建对象 4. 请设计一个类&#xff0c;不能被继承 5. 请设计一个类&#xff0c;只能创建一个对…...

J8学习打卡笔记

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 Inception v1算法实战与解析 导入数据数据预处理划分数据集搭建模型训练模型正式训练结果可视化详细网络结构图个人总结 import os, PIL, random, pathlib imp…...

前端学习-操作元素内容(二十二)

目录 前言 目标 对象.innerText 属性 对象.innerHTML属性 案例 年会抽奖 需求 方法一 方法二 总结 前言 曾经沧海难为水&#xff0c;除却巫山不是云。 目标 能够修改元素的文本更换内容 DOM对象都是根据标签生成的,所以操作标签,本质上就是操作DOM对象&#xff0c;…...

【踩坑】pip离线+在线在虚拟环境中安装指定版本cudnn攻略

pip离线在线在虚拟环境中安装指定版本cudnn攻略 在线安装离线安装Windows环境&#xff1a;Linux环境&#xff1a; 清华源官方帮助文档 https://mirrors.tuna.tsinghua.edu.cn/help/pypi/ 标题的离线的意思是先下载whl文件再安装到虚拟环境&#xff0c;在线的意思是直接在当前虚…...

golang操作sqlite3加速本地结构化数据查询

目录 摘要Sqlite3SQLite 命令SQLite 语法SQLite 数据类型列亲和类型——优先选择机制 SQLite 创建数据库SQLite 附加数据库SQLite 分离数据库 SQLite 创建表SQLite 删除表 SQLite Insert 语句SQLite Select 语句SQLite 运算符SQLite 算术运算符SQLite 比较运算符SQLite 逻辑运算…...

vllm加速(以Qwen2.5-7B-instruction为例)与流式响应

1. vllm介绍 什么是vllm? vLLM 是一个高性能的大型语言模型推理引擎&#xff0c;采用创新的内存管理和执行架构&#xff0c;显著提升了大模型推理的速度和效率。它支持高度并发的请求处理&#xff0c;能够同时服务数千名用户&#xff0c;并且兼容多种深度学习框架&#xff0c;…...

WordPress弹窗公告插件-ts小陈

使用效果 使用后网站所有页面弹出窗口 插件特色功能 设置弹窗公告样式&#xff1a;这款插件可展示弹窗样式公告&#xff0c;用户点击完之后不再弹出&#xff0c;不会频繁打扰用户。可设置弹窗中间的logo图&#xff1a;这款插件针对公告图片进行独立设置&#xff0c;你可以在设…...

【ELK】容器化部署Elasticsearch1.14.3集群【亲测可用】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1. 部署1.1 单节点1.2 新节点加入集群1.3 docker-compose部署集群 1. 部署 按照官网流程进行部署 使用 Docker 安装 Elasticsearch |Elasticsearch 指南 [8.14] |…...

[SAP ABAP] ALV状态栏GUI STATUS的快速创建

使用事务码SE38进入到指定程序&#xff0c;点击"显示对象列表"按钮 鼠标右键&#xff0c;选择"GUI状态" 弹出【创建状态】窗口&#xff0c;填写状态以及短文本描述以后&#xff0c;点击按钮 点击"调整模板"&#xff0c;复制已有程序的状态栏 填…...

【Linux】NET9运行时移植到低版本GLIBC的Linux纯内核板卡上

背景介绍 自制了一块Linux板卡(基于全志T113i) 厂家给的SDK和根文件系统能够提供的GLIBC的版本比较低 V2.25/GCC 7.3.1 这个版本是无法运行dotnet以及dotnet生成的AOT应用的 我用另一块同Cortex-A7的板子运行dotnet的报错 版本不够&#xff0c;运行不了 而我的板子是根本就识…...

深入浅出支持向量机(SVM)

1. 引言 支持向量机&#xff08;SVM, Support Vector Machine&#xff09;是一种常见的监督学习算法&#xff0c;广泛应用于分类、回归和异常检测等任务。自1990年代初期由Vapnik等人提出以来&#xff0c;SVM已成为机器学习领域的核心方法之一&#xff0c;尤其在模式识别、文本…...

Vue脚手架相关记录

脚手架 安装与配置 安装node node -> 16.20.2 切换淘宝镜像 npm install -g cnpm -registryhttp://registry.npm.taobao.orgnpm config set registry http://registry.npm.taobao.org/使用了第二个,下一步才有用 安装vue npm install -g vue/clivscode中不给运行vue解…...

基于Docker的Minio分布式集群实践

目录 1. 说明 2. 配置表 3. 步骤 3.1 放行服务端口 3.2 docker-compose 编排 4. 入口反向代理与负载均衡配置 4.1 api入口 4.2 管理入口 5. 用例 6. 参考 1. 说明 以多节点的Docker容器方式实现minio存储集群&#xff0c;并配以nginx反向代理及负载均衡作为访问入口。…...

Scala 的迭代器

迭代器定义&#xff1a;迭代器不是一种集合&#xff0c;它是一种用于访问集合的方法。 迭代器需要通过集合对应的迭代器调用迭代器的方法来访问。 支持函数式编程风格&#xff0c;便于链式操作。 创建一个迭代器&#xff0c;相关代码如下&#xff1a; object Test {def mai…...

vue实现文件流形式的导出下载

文章目录 Vue 项目中下载返回的文件流操作步骤一、使用 Axios 请求文件流数据二、设置响应类型为 ‘blob’三、创建下载链接并触发下载四、在 Vue 组件中集成下载功能五、解释与实例说明1、使用 Axios 请求文件流数据&#xff1a;设置响应类型为 blob&#xff1a;创建下载链接并…...

【DIY飞控板PX4移植】深入理解NuttX下PX4串口配置:ttyS设备编号与USARTUART对应关系解析

深入理解NuttX下PX4串口配置&#xff1a;ttyS设备编号与USART&UART对应关系解析 引言问题描述原因分析结论 引言 在嵌入式系统开发中&#xff0c;串口&#xff08;USART/UART&#xff09;的配置是一个常见但关键的任务。对于使用 NuttX 作为底层操作系统的飞控系统&#x…...

【报错解决】vsvars32.bat 不是内部或外部命令,也不是可运行的程序或批处理文件

报错信息&#xff1a; 背景问题&#xff1a;Boost提示 “cl” 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件时&#xff0c;   按照这篇博客的方法【传送】添加了环境变量后&#xff0c;仍然报错&#xff1a; 报错原因&#xff1a; vsvars32.bat 的路径不正…...

CTFshow-文件上传(Web151-170)

CTFshow-文件上传(Web151-170) 参考了CTF show 文件上传篇&#xff08;web151-170&#xff0c;看这一篇就够啦&#xff09;-CSDN博客 Web151 要求png&#xff0c;然后上传带有一句话木马的a.png&#xff0c;burp抓包后改后缀为a.php&#xff0c;然后蚁剑连接&#xff0c;找fl…...

深度学习基础--将yolov5的backbone模块用于目标识别会出现怎么效果呢??

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 yolov5网络结构比较复杂&#xff0c;上次我们简要介绍了yolov5网络模块&#xff0c;并且复现了C3模块&#xff0c;深度学习基础–yolov5网络结构简介&a…...

操作系统(16)I/O软件

前言 操作系统I/O软件是负责管理和控制计算机系统与外围设备&#xff08;例如键盘、鼠标、打印机、存储设备等&#xff09;之间交互的软件。 一、I/O软件的定义与功能 定义&#xff1a;I/O软件&#xff0c;也称为输入/输出软件&#xff0c;是计算机系统中用于管理和控制设备与主…...

DownKyi完全指南:三步解锁B站8K视频下载的终极方案

DownKyi完全指南&#xff1a;三步解锁B站8K视频下载的终极方案 【免费下载链接】downkyi 哔哩下载姬downkyi&#xff0c;哔哩哔哩网站视频下载工具&#xff0c;支持批量下载&#xff0c;支持8K、HDR、杜比视界&#xff0c;提供工具箱&#xff08;音视频提取、去水印等&#xff…...

Nix构建确定性AI编程环境:解决Cursor编辑器依赖冲突难题

1. 项目概述&#xff1a;当代码编辑器遇上Nix的确定性魔法 最近在折腾开发环境时&#xff0c;我遇到了一个老生常谈但又无比头疼的问题&#xff1a;团队里新来的同事怎么也跑不起来我本地运行得好好的一个代码辅助工具链。依赖版本冲突、系统库路径不对、甚至是因为他用的macO…...

【避坑指南】VSCode+EIDE+Keil混合开发环境:从零搭建到项目无缝迁移

1. 为什么需要VSCodeEIDEKeil混合开发环境&#xff1f; 作为一名嵌入式开发者&#xff0c;我深知Keil这个老牌IDE在开发效率上的痛点&#xff1a;代码补全弱、界面老旧、多窗口管理混乱。但直接完全迁移到VSCode又面临工程兼容性问题&#xff0c;特别是对传统AC5编译器的支持。…...

从TPM到机密计算:远程证明技术原理与zap1项目实践指南

1. 项目概述与核心价值最近在整理一些零散的学习笔记时&#xff0c;发现了一个挺有意思的项目&#xff0c;叫Frontier-Compute/zap1-learning-attestation。乍一看这个标题&#xff0c;可能有点让人摸不着头脑&#xff0c;尤其是对于刚接触可信计算或者硬件安全领域的朋友来说。…...

如何轻松管理Switch游戏:NS-USBLoader完整指南,三步搞定游戏安装与系统引导

如何轻松管理Switch游戏&#xff1a;NS-USBLoader完整指南&#xff0c;三步搞定游戏安装与系统引导 【免费下载链接】ns-usbloader Awoo Installer and GoldLeaf uploader of the NSPs (and other files), RCM payload injector, application for split/merge files. 项目地址…...

STM8硬件IIC驱动BNO055传感器避坑指南(附完整代码)

STM8硬件IIC驱动BNO055传感器实战解析与优化 BNO055作为一款集成了9轴传感器融合算法的智能芯片&#xff0c;能够直接输出姿态角数据&#xff0c;极大简化了嵌入式系统中姿态解算的复杂度。然而在实际应用中&#xff0c;许多开发者发现使用STM32等常见MCU的模拟IIC接口难以稳定…...

零基础实操:小龙虾 AI OpenClaw 接入 Kimi 详细步骤

前置准备 获取小龙虾open claw一键安装包&#xff08;www.totom.top&#xff09;并安装电脑端已成功安装并正常运行OpenClaw客户端&#xff0c;顶部 Gateway 状态保持在线设备网络通畅&#xff0c;可正常访问 Kimi 开放平台拥有可正常登录的 Kimi 月之暗面 Moonshot 账号账号提…...

数据质量保证:确保数据准确性和可靠性

数据质量保证&#xff1a;确保数据准确性和可靠性 一、数据质量保证概述 1.1 数据质量保证的定义 数据质量保证是指通过一系列技术和流程&#xff0c;确保数据的准确性、完整性、一致性和及时性的过程。它涉及数据采集、存储、处理和使用的各个环节&#xff0c;确保数据符合业务…...

量子最优控制中的iLQR算法实践与优化

1. 量子最优控制基础与挑战量子最优控制&#xff08;Quantum Optimal Control, QOC&#xff09;是现代量子计算中的核心技术&#xff0c;其核心目标是通过精心设计的控制脉冲序列&#xff0c;实现对量子系统状态演化的精确操控。在超导量子计算体系中&#xff0c;这一技术尤为重…...

汽车该多久换一代

汽车该多久换一代 买车的人其实不怕四年换代&#xff0c;怕的是刚提车半年就被新款打成旧款。李想这句话能引起讨论&#xff0c;原因也在这里&#xff1a;车企说的是研发验证周期&#xff0c;车主感受到的是价格、配置和二手残值。 汽车确实没法完全照着手机节奏跑。手机坏了可…...