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

【C++】特殊类设计

🌈欢迎来到C++专栏~~特殊类设计


  • (꒪ꇴ꒪(꒪ꇴ꒪ )🐣,我是Scort
  • 目前状态:大三非科班啃C++中
  • 🌍博客主页:张小姐的猫~江湖背景
  • 快上车🚘,握好方向盘跟我有一起打天下嘞!
  • 送给自己的一句鸡汤🤔:
  • 🔥真正的大师永远怀着一颗学徒的心
  • 作者水平很有限,如果发现错误,可在评论区指正,感谢🙏
  • 🎉🎉欢迎持续关注!
    在这里插入图片描述

请添加图片描述

文章目录

  • 🌈欢迎来到C++专栏~~特殊类设计
    • 🎃请设计一个类,不能被拷贝
    • 🎃请设计一个类,不能被继承
    • ✨请设计一个类,只能在堆上创建对象
    • ✨请设计一个类,只能在栈上创建对象
    • 😎请设计一个类,只能创建一个对象(单例模式)
      • 💢饿汉模式
      • 💢懒汉模式
  • 📢写在最后

请添加图片描述

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

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

1️⃣C++98

  • 将拷贝构造函数与赋值运算符重载只声明不定义,并且将其访问权限设置为私有即可
class CopyBan
{
public://...
private://C++98CopyBan(const CopyBan&);CopyBan& operator=(const CopyBan&);//C++11CopyBan(const CopyBan&) = delete;CopyBan& operator=(const CopyBan&) = delete;
};

原因:

  1. 设置成私有:如果只声明没有设置成private,用户自己如果在类外定义了,就可以不
    能禁止拷贝了
  2. 只声明不定义:不定义是因为该函数根本不会调用,定义了其实也没有什么意义,不写反而还简单,而且如果定义了就不会防止成员函数内部拷贝了

2️⃣C++11
delete除了释放new申请的资源外,如果在默认成员函数后跟上=delete,表示让编译器删除掉该默认成员函数

class CopyBan
{// ...CopyBan(const CopyBan&)=delete;CopyBan& operator=(const CopyBan&)=delete;//...
};

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

C++98:

  • 因为子类的构造函数被调用时,必须调用父类的构造函数初始化父类的那一部分成员,但父类的私有成员在子类当中是不可见的,所以在创建子类对象时子类无法调用父类的构造函数对父类的成员进行初始化,因此该类被继承后子类无法创建出对象。
class NonInherit
{
public:static NonInherit CreateObj(){return NonInherit();}
private://将构造函数设置为私有NonInherit(){}
};

C++11:

  • final关键字,final修饰类,表示该类不能被继承
class A  final
{// ....
};

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

只能在堆上创建对象,也就是只能通过new操作符创建对象,方式如下:

  1. 析构函数私有化
  2. 将类的构造函数私有,拷贝构造声明成私有或者delete掉。防止别人调用拷贝在栈上生成对象
  3. 提供一个静态static的成员函数,在该静态成员函数中完成堆对象的创建
class HeapOnly
{
public://3.提供一个公有的,获取对象的方式,对象控制是new出来的,static HeapOnly* CreatObj(){return new HeapOnly;}//防止拷贝HeapOnly(const HeapOnly& hp) = delete;HeapOnly& operator=(const HeapOnly& hp) = delete;
private://1.析构函数私有化~HeapOnly(){cout << "~HeapOnly" << endl;}//2.构造函数、拷贝构造都私有化  ~ new 也不可用了HeapOnly():_a(0){}
private:int _a;
};
int main()
{//1.析构函数私有了//HeapOnly hp1;//static HeapOnly hp2;//指针不会创建实际对象,所以不会调用到析构//HeapOnly* ptr = new HeapOnly;//ptr->Delete(ptr);HeapOnly* hp3 = HeapOnly::CreatObj();return 0;
}

🎃注意:

  • 向外部提供的CreateObj函数必须设置为静态成员函数,因为外部调用该接口就是为了获取对象的,而非静态成员函数必须通过对象才能调用,这就变成鸡生蛋蛋生鸡的问题了
  • C++98通过将拷贝构造函数声明为私有以达到防拷贝的目的,C++11可以在拷贝构造函数后面加上=delete,表示让编译器将拷贝构造函数删除,此时也能达到防拷贝的目的

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

方法1️⃣:

  1. 构造函数设置为私有,防止外部直接调用构造函数在堆上创建对象。
  2. 向外部提供一个获取对象的static接口,该接口在栈上创建一个对象并返回
class StackOnly
{
public:static StackOnly CreateObj(){StackOnly st;return st;}
private://构造函数私有StackOnly():_a(0){}
private:int _a;
};int main()
{StackOnly st1 = StackOnly::CreateObj();return 0;
}

但该方法有一个缺陷就是,无法防止外部调用拷贝构造函数创建对象

int main()
{StackOnly st1 = StackOnly::CreateObj();//调用拷贝构造static StackOnly copy(st1);StackOnly* copy2 = new StackOnly(st1);return 0;
}

但是我们不能将构造函数设置为私有,也不能用=delete的方式将拷贝构造函数删除,因为CreateObj函数当中创建的是局部对象,返回局部对象的过程中势必需要调用拷贝构造函数

此路不通,换一条

方法2️⃣:

  • 屏蔽operator new函数和operator delete函数,或者自己声明一个不实现
class StackOnly
{
public:StackOnly(){}
private://C++98void* operator new(size_t size);void operator delete(void* p);//C++11//void* operator new(size_t size) = delete;//void operator delete(void* p) = delete;
};

new和delete默认调用的是全局的operator new函数和operator delete函数,但如果一个类重载了专属的operator new函数和operator delete函数,那么new和delete就会调用这个专属的函数。所以只要把operator new函数和operator delete函数屏蔽掉,那么就无法再使用new在堆上创建对象了。

但该方法也有一个缺陷,就是无法防止外部在静态区创建对象。

static StackOnly obj; //在静态区创建对象

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

什么是单例模式?

  • 一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享
  • 比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理

单例模式有两种实现方式,分别是饿汉模式懒汉模式

💢饿汉模式

就是说不管你将来用不用,程序启动时就创建一个唯一的实例对象

  • 优点:简单,没有线程安全问题
  • 缺点
    • 1️⃣可能会导致进程启动慢,且如果有多个单例类对象实例启动顺序无法控制
    • 2️⃣饿汉单例类,初始化时任务多,会影响程序启动速度
//饿汉模式 : 一开始(main函数之前)就创建出对象
class MemoryPool
{
public://3、提供一个全局访问点获取单例对象static MemoryPool* GetInstance(){return _pinst;}void* Alloc(size_t n){void* ptr = nullptr;return ptr;}void* Dealloc(void* ptr){//...}private://构造函数私有,并且防止拷贝MemoryPool(){}char* _ptr = nullptr;//2、提供一个指向单例对象的static指针static MemoryPool* _pinst;//声明
};//在程序入口之前完成单例对象的初始化
MemoryPool* MemoryPool::_pinst = new MemoryPool;int main()
{void* ptr1 = MemoryPool::GetInstance()->Alloc(10);MemoryPool::GetInstance()->Dealloc(ptr1);return 0;
}

💢懒汉模式

特点:延迟加载,第一次使用对象再创建实例化对象

  • 优点:控制顺序、不影响启动速度
  • 缺点: 相对复杂(线程安全问题)、线程安全问题要处理好、
//懒汉模式 : 第一次使用对象时,再创建实例对象
class MemoryPool
{
public://3、提供一个全局访问点获取单例对象static MemoryPool* GetInstance(){//第一次来就newif (_pinst == nullptr){_pinst = new MemoryPool;}return _pinst;}void* Alloc(size_t n){void* ptr = nullptr;return ptr;}void* Dealloc(void* ptr){//...}private://构造函数私有,并且防止拷贝MemoryPool(){//...}char* _ptr = nullptr;//2、提供一个指向单例对象的static指针static MemoryPool* _pinst;//声明
};//在程序入口之前对象初始化为空
MemoryPool* MemoryPool::_pinst = nullptr;int main()
{void* ptr1 = MemoryPool::GetInstance()->Alloc(10);MemoryPool::GetInstance()->Dealloc(ptr1);return 0;
}

我们发现以上代码中,我们new出来好像都没有去释放,这就涉及到了单例对象释放问题

  1. 一般情况下,单例对象是不需要释放的:整个程序运行区间都要用到
  2. 单例对象在进程正常结束后,也会资源释放(特殊场景:对象析构时,要进行持久化操作

ps:往磁盘文件上写、往数据库中写就是持久化操作

📢写在最后

请添加图片描述

相关文章:

【C++】特殊类设计

&#x1f308;欢迎来到C专栏~~特殊类设计 (꒪ꇴ꒪(꒪ꇴ꒪ )&#x1f423;,我是Scort目前状态&#xff1a;大三非科班啃C中&#x1f30d;博客主页&#xff1a;张小姐的猫~江湖背景快上车&#x1f698;&#xff0c;握好方向盘跟我有一起打天下嘞&#xff01;送给自己的一句鸡汤&a…...

中创教育PMP如何轻松应对公司90%以上的沟通难题

掌握沟通技能&#xff0c;可以让问题从1变成0&#xff1b; 掌握沟通技能&#xff0c;可以让机会从0变成1&#xff1b; 掌握沟通技能&#xff0c;可以让成功从1变成100&#xff1b; 难题一、当领导问你某件事&#xff0c;但你又不太清楚时 【说话公式】需要思考需要确认晚点回…...

#笨鸟先飞# 数据结构与算法基础 课程笔记 第六章 图

图的定义和基本术语图&#xff1a;G( V , E ) Graph&#xff08;Vertex&#xff0c;Edge&#xff09;V&#xff1a;顶点&#xff08;数据元素&#xff09;的有穷非空集合&#xff1b;E&#xff1a;边的有穷集合。无向图&#xff1a;每条边都是无方向的有向图&#xff1a;每条边…...

深入浅出带你学习Apache中间件常见漏洞

前言 上一篇文章给大家总结了一下IIS中间件的漏洞&#xff0c;这篇文章就给大家讲一下apache中间件漏洞&#xff0c;说起apache大家一定不会陌生&#xff0c;这是我们日常中经常用到的中间件&#xff0c;下面由我来给大家讲解一下改中间件常见的漏洞。 Apache是什么&#xff…...

用多种指针方法访问数据元素,实现逆序输出

这里注意下数组指针的下标表示&#xff1a; 我们已经知道&#xff0c;数组名a总是指向a[0]的指针&#xff0c;*(ai)是对a[i]的引用&#xff0c;实际上&#xff0c;编译器中&#xff0c;对数组的引用&#xff0c;如a[i]&#xff0c;总是被编译器改写成*(ai)的形式。 另外说明下…...

WebDAV之葫芦儿·派盘+NMM

NMM 支持WebDAV方式连接葫芦儿派盘。 推荐一款文件管理器,可以对手机中的文件进行多方面的管理,支持语法高亮和ftp等远程的文件的管理。支持从WebDav服务器连接葫芦儿派盘服务下载文件和上传文件。 NMM文本编辑器是一款文件管理器,在功能上面更加的适合于一些编程人员进行使…...

Redis多级缓存

文章目录一. 什么是多级缓存二. JVM进程缓存一. 什么是多级缓存 传统的缓存策略一般是请求到达Tomcat后&#xff0c;先查询Redis&#xff0c;如果未命中则查询数据库&#xff0c;如图&#xff1a; 存在下面的问题&#xff1a; 请求要经过Tomcat处理&#xff0c;Tomcat的性能…...

【原创】java+swing+mysql会议室管理系统设计与实现

本文主要介绍使用javaswingmysql等技术去设计完成一个企业公司的会议室管理系统&#xff0c;帮助企业员工去进行会议室的预约安排。 功能分析&#xff1a; 会议室管理系统的使用角色&#xff0c;一般分为管理员和员工用户&#xff0c;管理员进行数据管理&#xff0c;员工进行…...

【Redis】Redis 常用数据类型操作 ① ( 数据库操作 | Redis 数据库连接参数 | Redis 数据库个数 | Redis 访问机制 )

文章目录一、Redis 数据库连接参数二、Redis 数据库个数三、Redis 访问机制一、Redis 数据库连接参数 连接 Redis 数据库 , 只需要 IP 地址 , 端口号 , 访问密码 即可 , 如果没有 设置 访问密码 可忽略该选项 ; Redis 默认端口号是 6379 ; 参考 【Redis】Redis 数据库 安装、…...

GAMES101-计算机图形学入门 LEC4: TRANSFORMATION-3D

本节课程视频地址&#xff1a;https://www.bilibili.com/video/BV1X7411F744/?p4 补充上一节课的一个内容&#xff0c;旋转矩阵的逆矩阵是它的转置&#xff0c;也就是说有R−θRθ−1RθTR_{-\theta} R_\theta^{-1}R_\theta^TR−θ​Rθ−1​RθT​ 上节课讲了&#xff0c;…...

robot实战:截取字符串

一&#xff1a;变量标识符号(1) Scalar型变量: "$"作为标识符号&#xff0c;例如&#xff1a;${var}&#xff0c; 这个打印log时只能用logset赋值&#xff1a;a: ${var} Set Variable abcb:${var2} Set Variable If ${Var}abc efgh ace 如果var的值和abc相等&#xf…...

【面经】滴滴测开一面

滴滴测开一面 面试官自我介绍面试者自我介绍大概实习多久&#xff1f;你在在校经历比较丰富&#xff0c;说一下打ACM那些比赛中的一些经验&#xff0c;找一些具体的项目说一下在打ACM中团队里几个人&#xff1f; 你负责什么&#xff1f;在上段实习的过程中都做了哪些事情&…...

数据治理-主数据

二、某企业集团旗下有房地产、供应链、物流、酒店等多个业务子公司&#xff0c;为了统一管理&#xff0c;集团推进数字化转型&#xff0c;建立了统一的数据仓库&#xff0c;各子公司将数据集成到集团信息部负责管理的 数据平台。集团在实施数据治理过程中&#xff0c;发现各业务…...

软考-中级-软件设计师-成绩

低分飘过&#xff0c;备考经验主要就是刷题。...

学习笔记<二> MySQL学习(3):分库、分表

文章目录为什么分库分表一、垂直分片、水平分片二、常用的数据分片策略三、垂直分表、垂直分库、水平分库、水平分表四、垂直切分、水平切分优缺点五、数据分片规则六、分库分表带来的问题本文参考博主「小Y是我的」的文章&#xff0c;原文链接&#xff1a;https://blog.csdn.n…...

重生之我是赏金猎人-SRC漏洞挖掘(八)-记一次移花接木的GetShell

0x00&#xff1a;前言 https://github.com/J0o1ey/BountyHunterInChina 欢迎亲们点个star 作者&#xff1a;RGM78sec 某天测厂商业务时&#xff0c;发现其中有一个提供音乐播放业务的资产&#xff0c;正好里面有我想听的歌&#xff0c;于是就有了这篇文章 0x01&#xff1a;…...

离线数仓(五):数仓搭建

文章目录一、创建数据库二、ODS 层&#xff08;原始数据层&#xff09;三、DWD 层&#xff08;明细数据层&#xff09;3.1 get_json_object 函数使用3.2 启动日志表 DWD层创建四、DWS 层&#xff08;服务数据层&#xff09;五、DWT 层&#xff08;数据主题层&#xff09;六、AD…...

安装SQL Server2017 过程中报KB29119355失败的解决方案

SQLServer 2017脱机版下载地址&#xff1a;http://download.microsoft.com/download/6/4/A/64A05A0F-AB28-4583-BD7F-139D0495E473/SQLServer2017-x64-CHS-Dev.isoMicrosoft SQL Server Management Studio 18管理工具下载https://learn.microsoft.com/zh-cn/sql/ssms/download-…...

2023年浙江建筑特种工(施工升降机)真题题库及答案

百分百题库提供特种工&#xff08;施工升降机&#xff09;考试试题、特种工&#xff08;施工升降机&#xff09;考试预测题、特种工&#xff08;施工升降机&#xff09;考试真题、特种工&#xff08;施工升降机&#xff09;证考试题库等,提供在线做题刷题&#xff0c;在线模拟考…...

2023年进入互联网行业好找工作吗?

俗话说&#xff1a;选择大于努力。年后求职小高峰&#xff0c;大家在找工作的时候选择肯定也多了。说真&#xff0c;不是人人都有铁饭&#xff0c;普通家庭的孩子想要在2023年进入互联网行业去找工作可能吗&#xff1f;01有一点大家要清楚&#xff0c;2022年是进入过一个寒冬的…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息&#xff0c;对客户进行统一管理&#xff0c;可以把所有客户信息录入系统&#xff0c;进行维护和统计功能。可通过文件的方式保存相关录入数据&#xff0c;对…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

LabVIEW双光子成像系统技术

双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制&#xff0c;展现出显著的技术优势&#xff1a; 深层组织穿透能力&#xff1a;适用于活体组织深度成像 高分辨率观测性能&#xff1a;满足微观结构的精细研究需求 低光毒性特点&#xff1a;减少对样本的损伤…...

拟合问题处理

在机器学习中&#xff0c;核心任务通常围绕模型训练和性能提升展开&#xff0c;但你提到的 “优化训练数据解决过拟合” 和 “提升泛化性能解决欠拟合” 需要结合更准确的概念进行梳理。以下是对机器学习核心任务的系统复习和修正&#xff1a; 一、机器学习的核心任务框架 机…...

CVE-2023-25194源码分析与漏洞复现(Kafka JNDI注入)

漏洞概述 漏洞名称&#xff1a;Apache Kafka Connect JNDI注入导致的远程代码执行漏洞 CVE编号&#xff1a;CVE-2023-25194 CVSS评分&#xff1a;8.8 影响版本&#xff1a;Apache Kafka 2.3.0 - 3.3.2 修复版本&#xff1a;≥ 3.4.0 漏洞类型&#xff1a;反序列化导致的远程代…...