【C++干货铺】常用的特殊类——饿汉模式和懒汉模式

=========================================================================

个人主页点击直达:小白不是程序媛

C++系列专栏:C++干货铺

代码仓库:Gitee

=========================================================================

目录

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

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

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

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

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

设计模式

单列模式

饿汉模式

懒汉模式


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

拷贝只会放生在两个场景中:

拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。

C++98

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

//C++98
//将拷贝构造函数和复制重载函数私有化
class CopyBan
{
public:
	 CopyBan()
	 {}
private:
	CopyBan(const CopyBan& );
	CopyBan& operator=(const CopyBan&);
};

原因:

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

C++11

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

//C++11
//使用关键字delete删除拷贝构造函数和赋值重载函数
class Copyban
{
	Copyban(const Copyban&) = delete;
	Copyban& operator=(const Copyban&)=delete;
};

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

实现方式:

  • 将类的构造函数私有,拷贝构造声明成私有。防止别人调用拷贝在栈上生成对象。
  • 提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建
class HeapOnly
{
public:
	static HeapOnly* Create()
	{
		return new HeapOnly;
	}
private:
	HeapOnly(){}
	//也可以使用delete关键字删除两个函数
	HeapOnly(const HeapOnly&) {}
 	HeapOnly& operator=(const HeapOnly&){}
};

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

实现方式:

同上将构造函数私有化,然后设计静态方法创建对象返回即可。

//将new和delete操作符删除
class StackOnly
{
public:
	static StackOnly Cerate()
	{
		//返回匿名对象
		return StackOnly();
	}
	void* operator new(size_t size)  = delete;
	void operator delete(void* ptr) = delete;
private:
	StackOnly() {};

};

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

C++98

//C++98 将构造函数私有化,派生类中调不到基类的构造函数,则无法被继承
class NonInherit
{
public:
	static NonInherit Cerate()
	{
		//返回匿名对象
		return NonInherit();
	}
private:
	NonInherit() {};

};

C++11

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

//C++11
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;
};

A A::_inst;
int main()
{
	//A aa1;
	//A aa2;

	A::GetInstance()->Add("sort", "排序");
	A::GetInstance()->Add("left", "左边");
	A::GetInstance()->Add("right", "右边");
	A::GetInstance()->Print();

	//禁用拷贝构造和赋值重载可以防止被拷贝生成其他类
	/*A copy(*A::GetInstance());
	copy.Print();

	A::GetInstance()->Add("left", "剩余");
	copy.Print();
	A::GetInstance()->Print();*/

	//*A::GetInstance() = *A::GetInstance();

	return 0;
}

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

懒汉模式

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

// 懒汉模式:第一次用的时候再创建(现吃现做)
// 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;

int main()
{
	B::GetInstance()->Add("sort", "排序");
	B::GetInstance()->Add("left", "左边");
	B::GetInstance()->Add("right", "右边");
	B::GetInstance()->Print();

	B::GetInstance()->Add("right", "xxx");
	B::GetInstance()->Print();
	
	//B::DelInstance();
	cout << "xxxxxxxxxxx" << endl;

	// 期望main函数结束后自动调用

	return 0;
}

今天给大家分享介绍了C++中的几种特殊的类。如果觉得文章还不错的话,可以三连支持一下,个人主页还有很多有趣的文章,欢迎小伙伴们前去点评,您的三连支持就是我前进的动力!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Maya的ai功能有哪些?Maya Assist是什么?

Autodesk Maya是一款流行的 3D 建模软件&#xff0c;艺术家和设计师使用它来创建现实的世界和表面。该软件以其与各种工具开发人员的合作而闻名&#xff0c;它允许多个工具的无缝集成以改进功能。Autodesk 的 Maya 刚刚发布了 Maya Assist&#xff0c;在 3D 建模和动画领域树立…

redis主从复制薪火相传

一.主从复制 1、是什么 主机数据更新后根据配置和策略&#xff0c; 自动同步到备机的master/slaver机制&#xff0c;Master以写为主&#xff0c;Slave以读为主 2、能干嘛 读写分离&#xff0c;性能扩展&#xff08;主 写 从 读&#xff09; 容…

瑞_力扣LeetCode_二叉搜索树相关题

文章目录 说明题目 450. 删除二叉搜索树中的节点题解递归实现 题目 701. 二叉搜索树中的插入操作题解递归实现 题目 700. 二叉搜索树中的搜索题解递归实现 题目 98. 验证二叉搜索树题解中序遍历非递归实现中序遍历递归实现上下限递归 &#x1f64a; 前言&#xff1a;本文章为瑞…

【验证码逆向专栏】最新某验三代滑块逆向分析,干掉所有的 w 参数!

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;不提供完整代码&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 本文章未…

EOCR-FEZ漏电保护器下低压工业领域的应用

电柜中常见的故障主要包括以下几种&#xff1a; 断路器故障&#xff1a;断路器是配电柜中的主要元件之一&#xff0c;常见的故障包括断路器拒动、误动、爆炸、烧毁等。这些故障可能是由于断路器的机械故障、电气故障或者是控制回路的问题所导致的。接触器故障&#xff1a;接触…

华为防火墙USG6000V1的NAT实验

实验拓扑&#xff1a; 之前实验做过&#xff0c;可以翻找之前的博客&#xff0c;各设备ip和接口已配好&#xff0c;均可可ping通防火墙。 实验要求&#xff1a; 一.生产区在工作时间内可以访问dmz区域&#xff0c;仅可以访问http服务器。 二.办公区全天可以访问dmz区域&…

Ceph篇之搭建Ceph可视化界面Dashboard

一、Ceph Dashboard Ceph 提供了原生的Dashboard功能&#xff0c;通过Dashboard可以获取Ceph集群的各种基本状态信息等。 二、搭建Ceph Dashboard step1&#xff1a;在每个mgr节点安装 yum install ceph-mgr-dashboard -ystep2&#xff1a;开启mgr功能 ceph mgr module enab…

全新PHP短网址生成系统,短链接生成系统,URL缩短器系统源码

PHP短网址系统URL缩短器平台&#xff0c;它使您可以轻松地缩短链接&#xff0c;根据受众群体的位置或平台来定位受众&#xff0c;并为缩短的链接提供分析见解。 系统使用了Laravel框架编写&#xff0c;前后台双语言使用&#xff0c;可以设置多域名&#xff0c;还可以开设套餐等…

python24.1.26读文件

打开文件 encoding:编码方式 程序会记录读文件的位置 读一部分文字&#xff1a; 读一行文字&#xff1a; 结合while循环 readlines结合for循环 关闭文件&#xff1a; 或者 实践&#xff1a;

【iOS ARKit】人脸检测追踪基础

在计算机人工智能&#xff08;Artificial Inteligence,AI&#xff09;物体检测识别领域&#xff0c;最先研究的是人脸检测识别&#xff0c;目前技术发展最成熟的也是人脸检测识别。人脸检测识别已经广泛应用于安防、机场、车站、闸机、人流控制、安全支付等众多社会领域&#x…

如何配置MacLinuxWindows环境变量

这里写目录标题 什么是环境变量什么是PATH为什么要配置环境变量 如何配置环境变量环境变量有哪些环境变量加载顺序环境变量加载详解 配置参考方法一&#xff1a; export PATHLinux环境变量配置方法二&#xff1a;vim ~/.bashrcLinux环境变量配置方法三&#xff1a;vim ~/.bash_…

从零开始:使用 Systemd 管理 Linux 服务的完全指南

从零开始&#xff1a;使用 Systemd 管理 Linux 服务的完全指南 引言Systemd 简介Systemd 与 SysVinit 的主要区别 Systemd 的核心组件1. systemctl2. systemd-journald3. systemd-analyze4. systemd-tmpfiles 管理服务启动和停止服务重启和重新加载服务查看服务状态管理服务自启…

超越传统,想修哪里就修哪里,SUPIR如何通过文本提示实现智能图像修复

项目简介 通过参数增加使得模型不仅能够修复图像中的错误或损坏&#xff0c;还能根据文本提示进行智能修复。例如根据描述来改变图像中的特定细节。这样的处理方式提升了图像修复的质量和智能度&#xff0c;使得模型能够更准确、更灵活地恢复和改进图像。 SUPIR的主要功能图像…

Azure AI - 沉浸式阅读器,阅读障碍用户福音

目录 一、什么是沉浸式阅读器将内容划分开来提高可读性显示常用字词的图片突出显示语音的各个部分朗读内容实时翻译内容将单词拆分为音节 二、沉浸式阅读器如何工作&#xff1f;环境准备创建 Web 应用项目设置身份验证配置身份验证值安装标识客户端 NuGet 包更新控制器以获取令…

InitVerse:为云计算服务带来更高的透明度和可验证性

InitVerse&#xff1a;为云计算服务带来更高的透明度和可验证性 在云计算服务领域&#xff0c;透明度和可验证性是构建信任的关键要素。传统的云计算市场往往缺乏透明度&#xff0c;用户难以了解其数据和计算资源的实际使用情况。然而&#xff0c;通过利用区块链技术&#xff0…

php下curl发送cookie

目录 一&#xff1a;使用 CURLOPT_COOKIE 选项 二&#xff1a;CURLOPT_COOKIEFILE 三&#xff1a;CURLOPT_HTTPHEADER php curl发送cookie的几种方式,下面来介绍下 一&#xff1a;使用 CURLOPT_COOKIE 选项 通过设置 CURLOPT_COOKIE 选项&#xff0c;你可以将 cookie 字符…

Python数值类型与数学函数:深入理解与高效应用

文章目录 一、Python的数字1.数值类型1.1 整型&#xff08;int&#xff09;1.2 浮点型&#xff08;float&#xff09;1.3 复数&#xff08;complex&#xff09; 2.数字类型转换2.1 int(x)2.2 float(x)2.3 complex(x)2.4 complex(x, y) 3.数字运算3.1 round 二、函数1.数学函数1…

【模拟算法系列】详解5道题

本文讲解模拟算法系列的5道经典题&#xff0c;在讲解题目的同时提供AC代码&#xff0c;点击题目即可打开对应OJ链接 目录 模拟算法的介绍 1、替换所有的问号 2、提莫攻击 3、 Z 字形变换 4、外观数列 5、数青蛙 模拟算法的介绍 题目中明确告诉你要干什么&#xff0c;思路…

在云服务器上通过FileZilla配置FTP(通过FileZilla配置FTP升级版)

有兴趣的读者可以看看博主的博客&#xff0c;有很全面的教程 阿里云之申请云服务器–配置jdk,tomcat,安全策略–能够在他人电脑上显示本电脑的Tomcat 通过FileZilla配置FTP 修改我们的安全组&#xff0c;将21&#xff0c;和50000-50010端口添加进去 加入实例即可&#xff0c;剩…

vue处理后端返回的文件数据流,并提供下载接口

返回的数据流 前端对其进行处理并下载 downloadFile(res, fileName) {// 使用后台返回的数据创建一个新的Blob对象 let blob new Blob([res]); // 如果fileName参数未定义或为空&#xff0c;则从res的headers中获取content-disposition字段&#xff0c;并从中提取文件名 if…