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 直接法

要使一个类只能在堆上创建对象,思路是:

  1. 将类的构造函数和拷贝构造函数私有,防止别人调用拷贝在栈上生成对象。
  2. 再提供一个静态成员函数,在该静态成员函数内部完成堆对象的创建。
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. 只能在栈上创建对象的类

要使一个类只能在栈上创建对象,思路是:

  1. 私有化构造函数
  2. 设计静态函数返回对象
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. 不能被继承的类

要使一个类不能被继承,方法是:

  1. c++98:基类析构函数私有,派生类不能调用基类的构造函数,无法编译通过
  2. c++11:使用final关键字标记基类,表示该类不能被继承

5. 单例模式

单例模式要求一个类只能创建一个对象,该模式可以抱枕系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。

单例模式有两种实现模式:

  1. 饿汉模式

  2. 懒汉模式

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;
}

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

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

相关文章

淘宝接口高并发采集核心要点解读,开启电商数据智能应用新纪元

一、引言 在电商蓬勃发展的今天&#xff0c;淘宝作为全球知名的电商巨头&#xff0c;其平台上的数据犹如一座蕴藏无限价值的宝藏。准确且高效地采集淘宝接口数据&#xff0c;并通过高并发技术实现大规模数据获取&#xff0c;对于电商企业的精准营销、市场趋势分析、竞品监测以及…

java: spire.pdf.free 9.12.3 create pdf

可以用windows 系统中文字体&#xff0c;也可以从文件夹的字体文件 /*** encoding: utf-8* 版权所有 2024 ©涂聚文有限公司* 许可信息查看&#xff1a;言語成了邀功盡責的功臣&#xff0c;還需要行爲每日來值班嗎* 描述&#xff1a;* # Author : geovindu,Geovin Du 涂…

C语言蓝桥杯组题目

系列文章目录 文章目录 系列文章目录前言题目第一题.1, 2, 3, 4 能组成多少个互不相同且无重复数字的三位数&#xff1f;都是多少&#xff1f;思路 第二题: 一个整数&#xff0c;它加上100后是一个完全平方数&#xff0c;再加上168又是一个完全平方数&#xff0c;请问该数是多少…

【TEST】Apache JMeter + Influxdb + Grafana

介绍 使用Jmeter发起测试&#xff0c;测试结果存入Influxdb&#xff0c;Grafana展示你的测试结果。 环境 windows 10docker desktopJDK17 安装 Apache JMeter 访问官网&#xff08;Apache JMeter - Apache JMeter™&#xff09;下载JMeter&#xff08;目前最新版本5.6.3&a…

基于python的长津湖评论数据分析与可视化,使用是svm情感分析建模

引言 研究背景及意义 上世纪初开始&#xff0c;中国电影就以自己独有的姿态登上了世界电影史的舞台。中国电影作为国家文化和思想观念的反映与延伸&#xff0c;能够增强文化自信&#xff0c;在文化输出方面有着极其重要的作用1[1]。 改革开放以来&#xff0c;随着生产力的提高…

表格数据处理中大语言模型的微调优化策略研究

论文地址 Research on Fine-Tuning Optimization Strategies for Large Language Models in Tabular Data Processing 论文主要内容 这篇论文的主要内容是研究大型语言模型&#xff08;LLMs&#xff09;在处理表格数据时的微调优化策略。具体来说&#xff0c;论文探讨了以下…

springboot/ssm网购平台管理系统Java在线购物商城管理平台web电商源码

springboot/ssm网购平台管理系统Java在线购物商城管理平台web电商源码 基于springboot(可改ssm)vue项目 开发语言&#xff1a;Java 框架&#xff1a;springboot/可改ssm vue JDK版本&#xff1a;JDK1.8&#xff08;或11&#xff09; 服务器&#xff1a;tomcat 数据库&…

Linux入门系列--文件与目录

一、介绍 在Linux中&#xff0c;有着一句话&#xff0c;叫做&#xff1a;一切皆文件。也就是任何东西都是以文件的形式存储的。 目录结构 bin&#xff1a;全程binary&#xff0c;含义是二进制。该目录中存储的都是一些二进制文件。我们学过C/C&#xff0c;其实也都知道机器能…

功能模块整合

程序架构 第一部分&#xff1a;所用到模块的初始化 第二部分&#xff1a;中断部分。利用定时中断实现呼吸灯、RTC显示时间、动态图片切换、超时检测以及息屏等功能 第三部分&#xff1a;主逻辑循环部分。采用的是状态机扫描的方式进行的&#xff0c;根据按键控制页编号变量&…

【创建型设计模式】工厂模式

【创建型设计模式】工厂模式 创建型设计模式第二期&#xff01;本期介绍简单工厂模式和工厂方法模式。 简单工厂模式 简单工厂模式&#xff08;又叫作静态工厂方法模式&#xff09;&#xff0c;其属于创建型设计模式&#xff0c;简单工厂模式不属于设计模式中的 23 种经典模…

RabbitMQ和RocketMQ相关面试题

RabbitMQ和RocketMQ面试题 RabbitMQ1.RabbitMQ各部分角色2.如何确保RabbitMQ消息的可靠性&#xff1f;3.什么样的消息会成为死信&#xff1f;4.死信交换机的使用场景是什么&#xff1f;5.TTL6.延迟队列7.消息堆积问题8.MQ集群 RocketMQ1.RocketMQ各部分角色2.RocketMQ如何保证高…

基于LLama_factory的Qwen2.5大模型的微调笔记

Qwen2.5大模型微调记录 LLama-facrotyQwen2.5 模型下载。huggingface 下载方式Modelscope 下载方式 数据集准备模型微调模型训练模型验证及推理模型导出 部署推理vllm 推理Sglang 推理 LLama-facroty 根据git上步骤安装即可&#xff0c;要求的软硬件都装上。 llama-factory运行…

Linux系统Docker部署开源在线协作笔记Trilium Notes与远程访问详细教程

目录 ⛳️推荐 前言 1. 安装docker与docker-compose 2. 启动容器运行镜像 3. 本地访问测试 4.安装内网穿透 5. 创建公网地址 6. 创建固定公网地址 ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下…

Spark——安装步骤详细教程

1、安装步骤 1、上传 cd /opt/modules 2、解压 tar -zxf spark-3.1.2-bin-hadoop3.2.tgz -C /opt/installs 3、重命名 cd /opt/installs mv spark-3.1.2-bin-hadoop3.2 spark-local 4、创建软链接 ln -s spark-local spark 5、配置环境变量&#xff1a; vi /etc/prof…

【知识科普】短链接生成系统设计

文章目录 什么是短链接一、基本原理二、生成过程三、重定向过程四、常用算法五、其他考虑因素 短链接系统设计1. 系统架构1.1 前端1.2 后端1.3 辅助组件 2. 短链生成算法2.1 唯一性保证2.2 短链格式 3. 流程设计3.1 长链接输入3.2 短链生成3.3 返回结果3.4 访问短链接 4. 安全考…

Vue第一篇:组件模板总结

前言 本文希望读者有一定的Vue开发经验&#xff0c;样例采用vue中的单文件组件&#xff0c;也是我的个人笔记&#xff0c;欢迎一起进步 必须有根元素 这是一个最简单的vue单文件组件&#xff0c;<template></template>被称为模板&#xff0c;模板中必须有一个根元素…

GEE 教程——分析特定区域的 Sentinel-2 图像数据,计算并导出中位数反射率

目录 代码解释 数据 代码 结果 引用 代码解释 这段代码用于在 Google Earth Engine 中处理 Sentinel-2 卫星图像,主要目标是计算特定区域的中位数反射率,并导出结果。以下是代码的主要功能和步骤: 1. **设置地图和区域**: - 将地图设置为混合视图。 - 定义感兴…

MacOS通过X11转发远程运行virt-manager进行虚机分配

今天需要通过本地macbook机器连接远程物理机&#xff0c;执行虚机分配&#xff0c;现有文档仅提供window环境安装&#xff0c;如下整理Mac环境下的安装步骤 操作篇 前提条件 支持x11转发的terminal&#xff0c;我本地使用iTerm2&#xff1b;本地安装XQuartz&#xff0c;作为…

flowable流程图详细绘制教程

文章目录 前言一、flowable是什么&#xff1f;回答下之前的问题 二、flowable-modeler使用1. 使用步骤2.开始绘制弄一个请假的流程 三 加载该流程总结 前言 flowable有些晦涩难懂的东西&#xff1a; 我最开始接触的时候,还是用的activity,当时觉得好复杂,那么这次经过我自己在…

LSA1类和2类区别

LSA 1类: Router-LSA【1类&#xff0c;生成者&#xff1a;每个运行ospf协议的路由器都会产生 作用&#xff1a;1类LSA描述自身链路状态信息】。 LSA2类&#xff1a; network-LAS【2类&#xff1b;生产者&#xff1a;DR产生&#xff1b;作用&#xff1a;描述一个MA网段路由信…