C++——特殊类

特殊类


文章目录

  • 特殊类
  • 一、请设计一个类,不能被拷贝
  • 二、请设计一个类,只能在堆上创建对象
    • 方案一:析构函数私有化
    • 方案二:构造函数私有化
  • 三、请设计一个类,只能在栈上创建对象
  • 四、请设计一个类,不能被继承
  • 五、请设计一个类,只能创建一个对象(单例模式)
    • 饿汉模式
    • 懒汉模式


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

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

C++98中:将拷贝构造函数与赋值运算符重载只声明不定义,并且将其访问权限设置为私有即可

原因:

  1. 设置成私有:如果只声明没有设置成private,用户自己如果在类外定义了,就可以不能禁止拷贝了
  2. 只声明不定义:不定义是因为该函数根本不会调用,定义了其实也没有什么意义,不写反而还简单,而且如果定义了就不会防止成员函数内部拷贝了,但一定要声明,不然会默认生成
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;//...
};

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

方案一:析构函数私有化

实现方式:

  1. 将类的析构函数设为私有
  2. 提供一个公有成员函数,在该公有成员函数中完成堆对象的析构
class HeapOnly
{
public:/*static void Destroy(HeapOnly* ptr){delete ptr;}*/void Destroy(){delete this;}
private:~HeapOnly(){cout << "~HeapOnly()" << endl;}
};

方案二:构造函数私有化

实现方式:

  1. 将类的构造函数私有,拷贝构造声明成私有或delete,防止别人调用拷贝在栈上生成对象
  2. 提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建
class HeapOnly
{
public:static HeapOnly* CreateObj(){return new HeapOnly;}private://C++98//HeapOnly(const HeapOnly& hp);//C++11HeapOnly(const HeapOnly& hp) = delete;HeapOnly(){cout << "HeapOnly()" << endl;}
};

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

实现方式:将构造函数私有化,然后设计静态方法创建对象返回

class StackOnly
{
public:static StackOnly CreateObj(){StackOnly obj;return obj;}void* operator new(size_t size) = delete;// 实现类专属的operator new// new这个类对象时,operator new就会调用这个,不会调全局的//StackOnly obj = StackOnly::CreateObj();//StackOnly* ptr = (StackOnly*)new StackOnly(obj);//void* operator new(size_t size)//{//	cout << "void* operator new(size_t size)" << endl;//	return malloc(size);//}private:StackOnly(){cout << "StackOnly()" << endl;}
};

值得注意的是,需要把operator new函数delete掉,否则如果在类外定义,还是可以动态开辟空间

class StackOnly
{
public:static StackOnly CreateObj(){StackOnly obj;return obj;}//void* operator new(size_t size) = delete;// 实现类专属的operator new// new这个类对象时,operator new就会调用这个,不会调全局的//StackOnly obj = StackOnly::CreateObj();//StackOnly* ptr = (StackOnly*)new StackOnly(obj);void* operator new(size_t size){cout << "void* operator new(size_t size)" << endl;return malloc(size);}private:StackOnly(){cout << "StackOnly()" << endl;}
};int main()
{StackOnly obj = StackOnly::CreateObj();StackOnly* ptr = (StackOnly*)new StackOnly(obj);return 0;
}

在这里插入图片描述

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

C++98:构造函数私有化,派生类中调不到基类的构造函数,则无法继承

class NonInherit
{
public:static NonInherit GetInstance(){return NonInherit();}
private:NonInherit(){}
};

C++11:final关键字,final修饰类,表示该类不能被继承

class A final
{// ....
};

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

设计模式:

设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结
为什么会产生设计模式这样的东西呢?
就像人类历史发展会产生兵法,最开始部落之间打仗时都是人拼人的对砍,后来春秋战国时期,七国之间经常打仗,就发现打仗也是有套路的,后来孙子就总结出了《孙子兵法》,写代码也是类似,也有套路

使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。,设计模式使代码编写真正工程化,设计模式是软件工程的基石脉络,如同大厦的结构一样

单例模式:

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

饿汉模式

饿汉模式
优点:简单
缺点:可能会导致进程启动慢,且如果有多个单例类对象实例启动顺序不确定

// 饿汉模式:提前(main函数启动时)创建好实例对象
// 优点:实现简单
// 缺点:1、可能会导致进程启动慢、2、如果两个单例有启动先后顺序,那么饿汉无法控制
class A
{
public:static A* GetInstance(){return &_inst;}void Add(const string& key, const string& value){_dict[key] = value;}void Print(){for (auto& kv : _dict){cout << kv.first << ":" << kv.second << endl;}cout << endl;}
private:A(){}A(const A& aa) = delete;A& operator=(const A& aa) = delete;map<string, string> _dict;int _n = 0;static A _inst;
};

如果这个单例对象在多线程高并发环境下频繁使用,性能要求较高,那么显然使用饿汉模式来避免资源竞争,提高响应速度更好

懒汉模式

懒汉模式
优点:第一次使用实例对象时创建对象,进程启动无负载,多个单例实例启动顺序自由控制
缺点:复杂

// 懒汉模式:第一次用的时候再创建(现吃现做)
// todo:线程安全问题
// new的懒汉对象一般不需要释放,进程正常结束会释放资源
// 如果需要做一些动作,比如持久化,那么可以利用gc类static对象搞定
class B
{
public:static B* GetInstance(){if (_inst == nullptr){_inst = new B;}return _inst;}void Add(const string& key, const string& value){_dict[key] = value;}void Print(){for (auto& kv : _dict){cout << kv.first << ":" << kv.second << endl;}cout << endl;}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;

此处需要注意的是由于懒汉模式的单例对象是new出来的,大部分情况下这个单例对象是不需要回收的,由于进程使用的是虚拟地址,由页表映射到物理地址,所以等进程结束时,会发生解页表操作,此时动态分配的空间在系统的层面上被回收了

但如果我们还是希望能够自主控制这个单例何时释放空间或者当main函数结束的时候单例能够自动回收空间的话,可以实现一个内部类,进行回收操作

理由:我们不能把new出来的单例对象放在单例的析构函数中delete,因为如果这样会发生无限递归函数的情况,导致栈溢出,所以我们需要额外写一个函数接口能够自主将new出的单例对象空间释放,同时我们希望main函数结束的时候,如果该空间未释放,能够做到自动回收这份new出来的空间,此时内部类的回收机制就完全符合了我们的要求,也就是说内部类是解决问题的最优解

如果单例对象构造十分耗时或者占用很多资源,比如加载插件, 初始化网络连接,读取文件等等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化,就会导致程序启动时非常的缓慢,所以这种情况使用懒汉模式(延迟加载)更好


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

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

相关文章

c++连接mysql

c连接mysql 安装mysql以及c对应的库进入数据库&#xff0c;创建数据库&#xff0c;表&#xff0c;并新建管理员用户编写c代码编译运行&#xff0c;测试结果头文件解释 安装mysql以及c对应的库 sudo apt-get update sudo apt-get install mysql-server sudo apt-get install li…

CISAW和CISP-PTE证书选择指南

&#x1f4e3;在信息安全领域&#xff0c;选择合适的证书可以为你的职业生涯增添光彩。很多从事信息渗透行业的朋友经常讨论CISP-PTE和CISAW之间的选择问题。今天就从4个方面带你详细了解这两张证书&#xff0c;帮你做出明智的选择&#xff01; 1️⃣证书的行业前景 &#x1f4…

python爬虫爬取网站

流程&#xff1a; 1.指定url(获取网页的内容) 爬虫会向指定的URL发送HTTP请求&#xff0c;获取网页的HTML代码&#xff0c;然后解析HTML代码&#xff0c;提取出需要的信息&#xff0c;如文本、图片、链接等。爬虫请求URL的过程中&#xff0c;还可以设置请求头、请求参数、请求…

Ubuntu系统安装 Redis

环境准备 Ubuntu 系统版本&#xff1a;22.04.3Redis 版本&#xff1a;6.2.12 检查本地 make 环境 make -version若没有安装&#xff0c;则需要安装 sudo apt install make检查本地 gcc 环境 gcc -version若没有安装&#xff0c;则需要安装 sudo apt install gcc。 sudo a…

Single-Head ViT;Faster Whisper;Transformer KF;Pick-and-Draw

本文首发于公众号&#xff1a;机器感知 Single-Head ViT&#xff1b;Faster Whisper&#xff1b;Transformer KF&#xff1b;Pick-and-Draw SHViT: Single-Head Vision Transformer with Memory Efficient Macro Design Recently, efficient Vision Transformers have shown …

【遥感专题系列】遥感影像信息提取之——人工目视解译

​遥感影像通过亮度值或像元值的高低差异&#xff08;反映地物的光谱信息&#xff09;及空间变化&#xff08;反映地物的空间信息&#xff09;来表示不同地物的差异&#xff0c;这是区分不同影像地物的物理基础。 ​人工解译是目前国内使用最多的一种影像提取方法&#xff0c;如…

算法练习-螺旋矩阵(思路+流程图+代码)

难度参考 难度&#xff1a;中等 分类&#xff1a;数组 难度与分类由我所参与的培训课程提供&#xff0c;但需要注意的是&#xff0c;难度与分类仅供参考。以下内容均为个人笔记&#xff0c;旨在督促自己认真学习。 题目 给定一个正整数n&#xff0c;生成一个包含1到 n^2 所有元…

API网关-Apisix RPM包方式自动化安装配置教程

文章目录 前言一、简介1. etcd简介2. APISIX简介3. apisix-dashboard简介 二、Apisix安装教程1. 复制脚本2. 增加执行权限3. 执行脚本4. 浏览器访问5. 卸载Apisix 三、命令1. Apisix命令1.1 启动apisix服务1.2 停止apisix服务1.3 优雅地停止apisix服务1.4 重启apisix服务1.5 重…

Android矩阵Matrix变换setRectToRect,Kotlin

Android矩阵Matrix变换setRectToRect&#xff0c;Kotlin 在 Android画布Canvas裁剪区域clipRect&#xff0c;Kotlin-CSDN博客 基础上&#xff0c;增加一个点&#xff0c;通过setRectToRect挖出Bitmap原图中心区域的一块放到目标RectF里面。 import android.content.Context imp…

Google Chrome 常用的几个参数

1 右键--Google Chrome--属性--目标 参数作用--disable-infobars此计算机将不会再收到 Google Chrome 更新&#xff0c;因为 Windows XP 和 Windows Vista 不再受支持。适用于 xp、2003 的 49.x.x.x 版本。示例1--ingore-certificate-errors忽略证书错误--disable-background-…

知识库建设这些工具来帮忙,企业工作效率翻倍

在当今深度信息化的年代&#xff0c;知识库成了企业不可或缺的一部分&#xff0c;它的建设与管理显得格外重要。然而&#xff0c;想要建设又好又高效的知识库并非易事。好消息是&#xff0c;有很多优秀的工具可以让这个过程变得更加轻松&#xff0c;今天我们就重点来探讨其中的…

excel中去掉单元格中两个数字之间的空格

excel中去掉单元格中两个数字之间的空格 使用公式&#xff1a;SUBSTITUTE(A1," “,”") 解释&#xff1a;将A1单元格中的空格查找出来并去掉。

搭建WebGL开发环境

前言 本篇文章介绍如何搭建WebGL开发环境 WebGL WebGL的技术规范继承自免费和开源的OpenGL ES标准&#xff0c;从某种意义上说&#xff0c;WebGL就是Web版的OpenGL ES&#xff0c;而OpenGL ES是从OpenGL中派生出来的。他们的应用环境有区别&#xff0c;一般来说&#xff1a;…

C++:第十四讲动态规划初步

每日C知识 想要在做C小游戏里实现等待效果&#xff0c;可以用Sleep。 Sleep函数可以使计算机程序&#xff08;进程&#xff0c;任务或线程&#xff09;进入休眠&#xff0c;使其在一段时间内处于非活动状态。 一般需要头文件windows.h。 注意"Sleep"首字母要大写…

ppt背景图片怎么设置?让你的演示更加出彩!

PowerPoint是一款广泛应用于演示文稿制作的软件&#xff0c;而背景图片是演示文稿中不可或缺的一部分。一个好的背景图片能够提升演示文稿的整体效果&#xff0c;使观众更加关注你的演示内容。可是ppt背景图片怎么设置呢&#xff1f;本文将介绍ppt背景图片设置的三个方法&#…

Spring-boot项目+Rancher6.3部署+Nacos配置中心+Rureka注册中心+Harbor镜像仓库+NFS存储

目录 一、项目概述二、环境三、部署流程3.1 Harbor部署3.1.1 docker安装3.1.2 docker-compose安装3.1.3 安装证书3.1.4 Harbor下载配置安装 3.2 NFS存储搭建3.3 Rancher平台配置3.3.1 NFS存储相关配置3.3.2 Harbor相关配置3.3.3 Nacos部署及相关配置3.3.4 工作负载deployment配…

ubuntu20.04 安装ROS2 记录

主要参考B站古月居的ROS2入门21讲 和 以下链接&#xff08;基本和视频上一致&#xff09; ubuntu20.04安装ROS2 详细教程_ubuntu20.04 ros2-CSDN博客 但是中间有些需要注意的地方&#xff0c; 1&#xff0c;添加源 步骤中提到 sudo curl -sSL https://raw.githubuserconten…

Redis冲冲冲——缓存三兄弟:缓存击穿、穿透、雪崩

目录 引出缓存击穿缓存穿透缓存雪崩 总结 引出 谈谈redis的击穿、穿透、雪崩。 缓存击穿 缓存击穿&#xff1a;redis中没有&#xff0c;但是数据库有 顺序&#xff1a;先查缓存&#xff0c;判断缓存是否存在&#xff1b;如果缓存存在&#xff0c;直接返回数据&#xff1b;如果…

【前端素材】bootstrap3 实现地产置业公司source网页设计

一、需求分析 地产置业公司的网页通常是该公司的官方网站&#xff0c;旨在向访问者提供相关信息和服务。这些网页通常具有以下功能&#xff1a; 公司介绍&#xff1a;网页通常包含有关公司背景、历史、核心价值观和使命等方面的信息。此部分帮助访问者了解公司的身份和目标。 …

人工视觉仍然需要图像采集卡

最初&#xff0c;图像采集卡被用作模拟视频数字转换器和图像缓冲器&#xff0c;但如今它们能够执行复杂的任务&#xff0c;例如图像处理。图像采集卡的设计不断发展&#xff0c;旨在提高系统性能并减少计算机处理需求。 除了图像采集之外&#xff0c;图像采集卡还执行机器视觉…