C++特殊类设计(不能被拷贝的类、只能在堆上创建对象的类、不能被继承的类、单例模式)
C++特殊类设计
在实际应用中,可能需要设计一些特殊的类对象,如不能被拷贝的类、只能在堆上创建对象的类、只能在栈上创建对象的类、不能被继承的类、只能创建一个对象的类(单例模式)。
1. 不能被拷贝的类
拷贝只会发生在两个场景中:拷贝构造函数和赋值运算符重载。因此,让一个类禁止被拷贝,只需要让其拷贝构造函数和赋值运算符重载不能被调用即可。
1.1 c++98做法
c++98通过将拷贝构造函数和赋值运算符重载只声明不定义,并将其访问权限设置为私有实现禁止被拷贝。
class CopyBan
{
private:CopyBan(const CopyBan& cb);CopyBan& operator=(const CopyBan & cb);
};
1.2 现代做法
使用c++11提供的delete
关键字“删除”拷贝构造函数和赋值运算符重载。
class CopyBan
{
private:CopyBan(const CopyBan& cb) = delete;CopyBan& operator=(const CopyBan& cb) = delete;
};
2. 只能在堆上创建对象的类
2.1 直接法
要使一个类只能在堆上创建对象,思路是:
- 将类的构造函数和拷贝构造函数私有,防止别人调用拷贝在栈上生成对象。
- 再提供一个静态成员函数,在该静态成员函数内部完成堆对象的创建。
class HeapOnly
{static HeapOnly* Create()//静态解决“先有函数还是现有对象问题”{return new HeapOnly;}
private:HeapOnly(){}
};
但此不能完全封死在栈上创建对象,如果通过 Create()
函数先创建一个堆上的对象,再使用默认拷贝构造拷贝堆上的对象,就能够实现在栈上创建对象。
HeapOnly* ho1 = HeapOnly::Create();
HeapOnly* ho2(ho1);
所以最后还需要封死通过拷贝构造创建栈上对象:
c++98:
private:HeapOnly& HeapOnly(const HeapOnly& ho){}
c++11:
HeapOnly& HeapOnly(const HeapOnly& ho)=delete;
2.2 私有析构函数法
设计不能被拷贝的类还有一种方法,通过私有化析构函数,让栈上对象无法在离开作用域时自动调用析构函数,因此在栈上的创建对象的代码都不能被编译通过。再设计一个 release()
函数手动释放堆上的对象。
class HeapOnly
{
public:static HeapOnly* Create(){return new HeapOnly;}void relase(){delete this;}
private:~HeapOnly(){}
};
3. 只能在栈上创建对象的类
要使一个类只能在栈上创建对象,思路是:
- 私有化构造函数
- 设计静态函数返回对象
class StackOnly
{
public:static StackOnly Create(){return StackOnly();}void* operator new(size_t size) = delete;void operator delete(void* p) = delete;private:StackOnly():_a(0){}int _a;
};
设计只能在栈上创建对象的类还要注意将new和delete删除,避免使用new通过拷贝构造创建堆上对象。且由于 Create()
函数被设计成传值返回,不能直接通过删除拷贝构造实现(因为临时对象)。
删除new和delete的原理是,编译器默认生成一个new和一个delete,现将重载new和delete在类中重载,那么类对象会调用重载的new和重载的delete(重载后不再默认生成),但由于重载的new和重载的delete被删除,类对象在创建时便无法使用。
StackOnly so1 = StackOnly::Create();
StackOnly* so2 = new StackOnly(so1);
4. 不能被继承的类
要使一个类不能被继承,方法是:
- c++98:基类析构函数私有,派生类不能调用基类的构造函数,无法编译通过
- c++11:使用final关键字标记基类,表示该类不能被继承
5. 单例模式
单例模式要求一个类只能创建一个对象,该模式可以抱枕系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。
单例模式有两种实现模式:
-
饿汉模式
-
懒汉模式
5.1 饿汉模式
饿汉形容程序对对象的需要比较紧迫,不管将来用不用,在程序启动时就马上先创建一个唯一的实例对象(一般在main函数之前创建)。
#include<iostream>
using namespace std;class ehan
{
public:static ehan* GetInstance(){return &_e;}int SetInfo(int info){_info = info;return _info;}ehan(const ehan& e) = delete;ehan& operator=(const ehan& e) = delete;
private:ehan(){}int _info;static ehan _e;//声明
};ehan ehan::_e;//定义
int main()
{cout<<ehan::GetInstance()->SetInfo(1);return 0;
}
优先:简单
缺点:可能会导致进程启动慢,且如果有多个单例类使用饿汉模式,它们的对象实例启动顺序不确定
5.2 懒汉模式
懒汉模式可以完美解决饿汉模式的缺点,懒汉模式一般在第一次调用 GetInstance()
的时候创建单例对象。
#include<iostream>
using namespace std;class lanhan
{
public:static lanhan* GetInstance(){static lanhan _lh;return &_lh;}int SetInfo(int info){_info = info;return _info;}lanhan(const lanhan& e) = delete;lanhan& operator=(const lanhan& e) = delete;
private:lanhan(){}int _info;
};int main()
{cout<<lanhan::GetInstance()->SetInfo(1);return 0;
}
这里在
GetInstance()
里 定义了一个局部静态对象static lanhan _lh;
,即使调用多次GetInstance()
,这个创建对象的代码也只会执行一次,但这种使用方法是c++11之后支持,且有线程安全风险。
传统且线程安全方法:
#include<iostream>
#include<mutex>
using namespace std;class lanhan
{
public:static lanhan* GetInstance(){if (_lh == nullptr)//双重检查保证线程安全{unique_lock<mutex> lock(_mtx);if (_lh == nullptr){_lh = new lanhan;}}return _lh;}int SetInfo(int info){_info = info;return _info;}lanhan(const lanhan& e) = delete;lanhan& operator=(const lanhan& e) = delete;
private:lanhan(){}int _info;static mutex _mtx;static lanhan* _lh;};
lanhan* lanhan::_lh = nullptr;
mutex lanhan::_mtx;int main()
{cout<<lanhan::GetInstance()->SetInfo(1);return 0;
}
相关文章:
C++特殊类设计(不能被拷贝的类、只能在堆上创建对象的类、不能被继承的类、单例模式)
C特殊类设计 在实际应用中,可能需要设计一些特殊的类对象,如不能被拷贝的类、只能在堆上创建对象的类、只能在栈上创建对象的类、不能被继承的类、只能创建一个对象的类(单例模式)。 1. 不能被拷贝的类 拷贝只会发生在两个场景…...
Javaweb前端HTML css 整体布局
最后一个是线条颜色 盒子,整体还是300,400...
数据集-目标检测系列- 花卉 鸡蛋花 检测数据集 frangipani >> DataBall
数据集-目标检测系列- 花卉 鸡蛋花 检测数据集 frangipani >> DataBall DataBall 助力快速掌握数据集的信息和使用方式,会员享有 百种数据集,持续增加中。 贵在坚持! 数据样例项目地址: * 相关项目 1)数据集…...
【从零开始的LeetCode-算法】3297. 统计重新排列后包含另一个字符串的子字符串数目 I
给你两个字符串 word1 和 word2 。 如果一个字符串 x 重新排列后,word2 是重排字符串的 前缀,那么我们称字符串 x 是 合法的 。 请你返回 word1 中 合法 子字符串的数目。 示例 1: 输入:word1 "bcca", word2 "…...
【Redis_Day5】String类型
【Redis_Day5】String类型 String操作String的命令set和get:设置、获取键值对mset和mget:批量设置、获取键值对setnx/setex/psetexincr和incrby:对字符串进行加操作decr/decrby:对字符串进行减操作incrbyfloat:浮点数加…...
【CVE-2024-48694】OfficeWeb365 SaveDraw
漏洞描述 OfficeWeb365 v.8.6.1.0和v7.18.23.0中的文件上传漏洞允许远程攻击者通过pw/savedraw组件执行任意代码。 影响版本: V8.6.1.0; V7.18.23.0 网络测绘 “OfficeWeb365” 漏洞信息 POST /PW/SaveDraw?path../../Content/img&idx6.ashx H…...
leecode134.加油站
一开始想的是总体上加油量超过耗油量那么就一定能找到一个起始点可以跑一圈,这个起始点选择补充油量与耗油量差值最大的那gas个点,但是我没仔细审题,这个起始点是索引逐次1绕一圈而不是随便选择,gas[5,8,2,8],cost[6,5…...
分层架构 IM 系统之 Entry 部署模式
在前面的一篇技术短文(分层架构 IM 系统之架构解读)中,对【分层架构】进行了详细分析;今天我们聊一下【入口层】Entry 的部署模式。 Entry 作为 IM 系统整个后端集群的入口,直接与客户端建立 TCP 长连接,E…...
【Java从入门到放弃 之 多线程 四】
多线程 四 多线程 四读写锁的使用代码演示 乐观锁的使用代码演示 信号量代码演示 倒计时门禁代码演示 循环栅栏Condition详解代码案例 多线程 四 读写锁的使用 上一篇我们介绍到了可重入锁,现在我们来介绍读写锁。实际上,使用可重入锁的时候我们就可以…...
OpenHarmony-3.驱动HDF
OpenHarmony HDF 框架 1.OpenHarmony HDF 框架概述 OpenHarmony驱动子系统采用C面向对象编程模型构建,通过平台解耦、内核解耦,兼容不同内核,提供了归一化的驱动平台底座,旨在为开发者提供更精准、更高效的开发环境,力…...
udp_socket
文章目录 UDP服务器封装系统调用socketbind系统调用bzero结构体清0sin_family端口号ip地址inet_addrrecvfromsendto 新指令 netstat -naup (-nlup)包装器 的两种类型重命名方式包装器使用统一可调用类型 关键字 typedef 类型重命名系统调用popen关于inet_ntoa UDP服务器封装 系…...
Java NIO 核心知识总结
在学习 NIO 之前,需要先了解一下计算机 I/O 模型的基础理论知识。还不了解的话,可以参考我写的这篇文章:Java IO 模型详解。 一、NIO 简介 在传统的 Java I/O 模型(BIO)中,I/O 操作是以阻塞的方式进行的。…...
音频信号采集前端电路分析
音频信号采集前端电路 一、实验要求 要求设计一个声音采集系统 信号幅度:0.1mVpp到1Vpp 信号频率:100Hz到16KHz 搭建一个带通滤波器,滤除高频和低频部分 ADC采用套件中的AD7920,转换率设定为96Ksps ;96*161536 …...
PyTorch基础学习03_数学运算自动微分
目录 一、数学运算 1、基本操作 2、三角函数 3、统计学函数 二、保存和加载 三、并行化 四、自动微分 1、相关概念 2、计算梯度 1.标量梯度计算 2.向量梯度计算 3.多标量梯度计算 4.多向量梯度计算 5.矩阵梯度计算 3、梯度上下文控制 1、梯度控制 2、梯度更新…...
HarmonyOS4+NEXT星河版入门与项目实战(16)------ 状态管理 @State(页面数据刷新与渲染)
文章目录 1、@State装饰器2、视图渲染演示1、无嵌套的对象属性值变化时可以触发页面渲染2、嵌套对象的嵌套属性值变化时不能够触发页面刷新渲染3、数组中对象的属性值变化时不能触发页面刷新渲染3、总结1、@State装饰器 2、视图渲染演示 常规的 string、number 这里就不演示了…...
K8s 一键部署 MongoDB 的 Replica-Set 和 MongoDB-Express
什么是 MongoDB 副本集? MongoDB 副本集(Replica-Set)是一个分布式数据库系统,它包含一个主节点和多个从节点。主节点负责处理所有写操作,从节点用于读取数据。当主节点发生故障时,从节点可以自动选举一个…...
React Native的界面与交互
React Native (RN) 是一个由 Facebook 开发的开源框架,用于构建跨平台的移动应用程序。它允许开发者使用 JavaScript 和 React 来创建原生 iOS 和 Android 应用。RN 的出现极大地简化了移动应用的开发过程,使得开发者可以更快速、更高效地构建高质量的应…...
【探寻密码的奥秘】-001:解开密码的神秘面纱
目录 1、密码学概述1.1、概念1.2、目的1.3、应用场景 2、密码学的历史2.1、第一时期:古代密码时代2.2、第二时期:机械密码时代2.3、第三时期:信息密码时代2.4、第四时期:现代密码时代 3、密码学的基本概念3.1、一般通信系统3.2、保…...
C++实现Raft算法
概念部分 Raft 算法是一种用于实现分布式系统中的一致性的算法。它是为了容易理解而设计的,其目标是实现和 Paxos 算法相同的功能,但更加容易理解和实现。Raft 算法在分布式系统中尤其关键,因为它帮助系统中的多个节点就其数据的准确状态达成…...
FastApi教程
FastAPI框架 fastapi,一个用于构建 API 的现代、快速(高性能)的web框架。 fastapi是建立在Starlette和Pydantic基础上的,Pydantic是一个基于Python类型提示来定义数据验证、序列化和文档的库。Starlette是一种轻量级的ASGI框架/…...
HTB:WifineticTwo[WriteUP]
目录 连接至HTB服务器并启动靶机 信息搜集 使用rustscan对靶机TCP端口进行开放扫描 使用nmap对靶机开放端口进行脚本、服务扫描 使用curl访问靶机8080端口 使用浏览器直接访问/login路径 漏洞利用 使用searchsploit搜索该WebAPP漏洞 Payload USER_FLAG:bb…...
ubuntu16.04在ros使用USB摄像头-解决could not open /dev/video0问题
首先检查摄像头 lsusb 安装 uvc camera 功能包 sudo apt-get install ros-indigo-uvc-camera 安装 image 相关功能包 sudo apt-get install ros-kinetic-image-* sudo apt-get install ros-kinetic-rqt-image-view运行 uvc_camera 节点 首先输入roscore 然后另外开一个终端输入…...
大模型专栏--什么是大模型
什么是大模型 来自 chatGPT 的回答: “大模型”通常指的是在机器学习和深度学习领域,尤其是自然语言处理(NLP)和计算机视觉(CV)中,具有大量参数和复杂结构的模型。这些模型通常需要大量的数据和…...
LLaMA-Mesh: Unifying 3D Mesh Generation with Language Models 论文解读
目录 一、概述 二、相关工作 1、LLMs到多模态 2、3D对象生成 3、自回归的Mesh生成 三、LLaMA-Mesh 1、3D表示 2、预训练模型 3、有监督的微调数据集 4、数据集演示 四、实验 1、生成的多样性 2、不同模型text-to-Mesh的比较 3、通用语境的评估 一、概述 该论文首…...
golang实现TCP服务器与客户端的断线自动重连功能
1.服务端 2.客户端 生成服务端口程序: 生成客户端程序: 测试断线重连: 初始连接成功...
项目实战:基于深度学习的人脸表情识别系统设计与实现
大家好,人脸表情识别是计算机视觉领域中的一个重要研究方向,它涉及到对人类情感状态的理解和分析。随着深度学习技术的发展,基于深度学习的人脸表情识别系统因其高精度和强大的特征学习能力而受到广泛关注。本文旨在探讨基于深度学习的人脸表…...
【mongodb】社区版8:改变配置bindip和授权
更改配置 sudo systemctl restart mongod (base) root@k8s-master-pfsrv:/home/zhangbin# sudo tail -n 20 /var/log/mongodb/mongod.log 日志感觉是成功了:{"t":{"$date":"2024-11-19T19:57:47.076+08:00"...
python入门9-函数基础
函数介绍 <1>什么是函数 请看如下代码: print(" _ooOoo_ ") print(" o8888888o ") print(" 88 . 88 ") print(" …...
AMD(Xilinx) FPGA配置Flash大小选择
目录 1 FPGA配置Flash大小的决定因素2 为什么选择的Flash容量大小为最小保证能够完成整个FPGA的配置呢? 1 FPGA配置Flash大小的决定因素 在进行FPGA硬件设计时,选择合适的配置Flash是我们进行硬件设计必须考虑的,那么配置Flash大小的选择由什…...
TypeScript学习笔记(二)
接一 四、类型声明 使用 : 来对变量或函数形参,进行类型声明: let a: string //变量a只能存储字符串 let b: number //变量b只能存储数值 let c: boolean //变量c只能存储布尔值 a hello a 100 //警告:不能将类型“number”分配给类型“…...
Centos Stream 9安装Jenkins-2.485 构建自动化项目步骤
官网:https://www.jenkins.io/ 1 下载 环境准备: 版本支持查询:https://pkg.jenkins.io/redhat-stable/ 安装JDK17:https://blog.csdn.net/qq_44870331/article/details/140784297 yum -y install epel-release wget upgradew…...
多目标粒子群优化(Multi-Objective Particle Swarm Optimization, MOPSO)算法
概述 多目标粒子群优化(MOPSO) 是粒子群优化(PSO)的一种扩展,用于解决具有多个目标函数的优化问题。MOPSO的目标是找到一组非支配解(Pareto最优解),这些解在不同目标之间达到平衡。…...
【网络系统管理】2023年全国职业院校技能大赛:组策略--10套题组合--1
1、限制访问C盘; (1)搜索《我的电脑》 (2)用户配置\策略\管理模板\Windows组件\文件资源管理器 2、禁止运行run.exe; (1)搜索《应用程序》 (2)用户配置\策略\管理模板\系统...
【Golang】——Gin 框架中的 API 请求处理与 JSON 数据绑定
在现代 Web 开发中,API(特别是 RESTful API)是前后端分离架构的核心。Gin 框架提供了丰富的功能来处理 API 请求和 JSON 数据,使得开发者可以快速构建高效的接口服务。本篇博客将从基础到深入,全面讲解如何使用 Gin 框…...
在Linux下配置gitee与Github的远程仓库
目录 前言 云服务器下载git 检测是否下载成功git Linux下配置gitee远程仓库 代码提交演示 git三板斧 Linux下配置Github远程仓库 最后的提醒 前言 那么本篇文章将是在,你已经创建了本地仓库的基础上,在Linux下配置gitee的远程仓库的步骤ÿ…...
自动化测试过程操作细节
一、软件与框架介绍 1. Postman 读音:[pəʊstmən](剖斯特曼) 介绍:API开发与测试的得力助手,通过直观界面发送HTTP请求,查看响应数据。支持环境变量、集合、脚本等功能。 主要特点:易于使用…...
iic协议
IIC(Inter-Integrated Circuit)协议,也被称为I2C协议,是一种由荷兰的PHILIPS公司(现为NXP半导体公司)开发的简单、高效的通信协议。以下是关于IIC协议的详细介绍: 一、IIC协议概述 定义&#…...
uniapp、js判断输入的内容是整数
清奇的思路 通过取余运算符 % 来检查 输入的内容是否为整数 for (var i 0; i < this.list.length; i) {if (this.list[i].times % 1 ! 0) { // 使用取余运算符检查是否为整数uni.showToast({icon: none,title: 请输入整数的套餐次数,})return;}}...
《Qt Creator:人工智能时代的跨平台开发利器》
《Qt Creator:人工智能时代的跨平台开发利器》 一、Qt Creator 简介(一)功能和优势(二)快捷键与效率提升(三)跨平台支持(四)工具介绍与使用主要特性:使用步骤…...
The Yarn application application_xxx_xxx doesn‘t exist in RM
本文主要解决flink在standalone模式下,flink run却一直使用yarn-session模式的问题。 问题 有个客户找到笔者,问题是报错如下: 分析 笔者先从环境入手,首先要确定的是flink是使用了什么模式。确认过后是使用standalone模式。 那就很奇怪&a…...
爬虫实战:采集知乎XXX话题数据
目录 反爬虫的本意和其带来的挑战目标实战开发准备代码开发发现问题1. 发现问题[01]2. 发现问题[02] 解决问题1. 解决问题[01]2. 解决问题[02] 最终结果 结语 反爬虫的本意和其带来的挑战 在这个数字化时代社交媒体已经成为人们表达观点的重要渠道,对企业来说&…...
【C++篇】像解谜一样转换字符串:stoi 带你走向整数的世界
文章目录 前言 在现代 C 编程中,字符串与数字之间的转换是非常常见的需求。随着编程语言的发展,C 提供了多种方式来处理这种转换。stoi(string to integer)函数正是为了简化这一任务而被引入的。 在 C 的早期版本中,字…...
小U数数问题
问题描述 小U正在数偶数,从 0,2,4,6,8,10,12,…0,2,4,6,8,10,12,… 开始,依次将这些数连在一起,形成一个无穷长的字符串,例如:"0246810121416..."。小U想知道这个字符串中的第 nn 个字符是什么。 测试样例 …...
Rocky Linux 系统安装/部署 Docker
1、下载docker-ce的repo文件 [rootlocalhost ~]# curl https://download.docker.com/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker.repo % Total % Received % Xferd Average Speed Time Time Time Current Dloa…...
程序语言语法上手题目合集
程序语言语法上手题目合集 1跑步2猜年龄3Vigenre 密码 1跑步 2.跑步 - 蓝桥云课 枚举日期,判断是否符合条件即可。 参考程序: #include<stdio.h> int y2022,m1,d1; int week6; int month[13]{0,31,28,31,30,31,30,31,31,30,31,30,31};int judg…...
MCU通过APB总线与FPGA 数据交互(实现JATG 模块的控制)
问题出发点: 通过MCU 的APB 将数据发送到fpga 端;fpga 端实现 jtag 模块功能,支持状态机TAP的移动主要是:从IDLE 移动到 shirft-IR 发送指令数据然后再回到 IDLE ,从 IDLE 移动到shirft-DR 发送用户数据再回到IDLE;从而可以 通过 mcu端实现jtag 协议控制。 为了实现 MC…...
Mysql的UPDATE(更新数据)详解
MySQL的UPDATE语句是用于修改数据库表中已存在的记录,本文将详细介绍UPDATE语句的基本语法、高级用法、性能优化策略以及注意事项,帮助您更好地理解和应用这一重要的SQL命令。 1. 基本语法 单表更新 单表更新的基本语法如下: UPDATE [LOW…...
【AI最前线】DP双像素sensor相关的AI算法全集:深度估计、图像去模糊去雨去雾恢复、图像重建、自动对焦
Dual Pixel 简介 双像素是成像系统的感光元器件中单帧同时生成的图像:通过双像素可以实现:深度估计、图像去模糊去雨去雾恢复、图像重建 成像原理来源如上,也有遮罩等方式的pd生成,如图双像素视图可以看到光圈的不同一半&#x…...
如何使用AWS Lambda构建一个云端工具(超详细)
首发地址(欢迎大家访问):如何使用AWS Lambda构建一个云端工具(超详细) 1 前言 1.1 无服务器架构 无服务器架构(Serverless Computing)是一种云计算服务模型,它允许开发者构建和运行…...
Scala—数组(数组定义、数组常用方法等)— 用法详解
Scala Scala-数组-用法详解 Scala一、数组的定义1. new 关键字2. Array 对象的 apply 方法3. 创建多维数组 二、数组常用方法1. length:获取数组的长度。2. apply:通过索引获取数组中的元素。3. update:通过索引更新数组中的元素。4. foreach…...