【C++】-还在玩普通的类吗,这里面有好几种特殊的类的设计,快进来看看

news2024/11/9 3:42:51

在这里插入图片描述
💖作者:小树苗渴望变成参天大树🎈
🎉作者宣言:认真写好每一篇博客💤
🎊作者gitee:gitee✨
💞作者专栏:C语言,数据结构初阶,Linux,C++ 动态规划算法🎄
如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧!

文章目录

  • 前言
  • 一、请设计一个类,不能被拷贝
  • 二、请设计一个类,只能在堆上创建对象
  • 三、 请设计一个类,只能在栈上创建对象
  • 四、请设计一个类,不能被继承
  • 五、请设计一个类,只能创建一个对象(单例模式)
    • 5.1饿汉模式
    • 5.2懒汉模式
  • 六、总结


前言

今天我们讲解特殊类的设计,再我们的开发中难免会出现一些特殊情况,也是设计出一些特殊的类,他们和普通类不同担忧很相似,接下来博主会带大家设计出五种特殊的类,话不多说,我们开始进入正文的讲解。


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

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

C++98的使用方法:
class A
{
private:
	A(const A& a){}
	A& operator=(const A& a){}
};

C++11的用法:
class A
{
public:
	A(const A& a)=delete;
	A& operator=(const A& a)=delete;
private:
	
};

C++11扩展delete的用法,delete除了释放new申请的资源外,如果在默认成员函数后跟上
=delete,表示让编译器删除掉该默认成员函数。不拷贝再下面几个场景都需要使用到,防拷贝的用法

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

第一种方式:

class heaponly
{
public:


private:
	~heaponly(){}

};
int main()
{
	heaponly p0;//这样会报错
	heaponly* p2 = new heaponly;
	return 0;
}

原因是p2可以手动进行释放,但是需要再类中写一个接口来进行释放:
在这里插入图片描述

第二种方式:

class heaponly
{
public:
	static heaponly* creakobj()
	{
		return new heaponly;
	}
private:
	//1.先将构造函数私有化
	heaponly(){}
	
	//3.防拷贝
	heaponly(const heaponly& h) = delete;
	heaponly& operator=(const heaponly& h) = delete;
};

将构造函数私有化,都创建不了对象在这里插入图片描述所以写一个接口,通过调用接口来实现创建对象。但是调用函数需要,这时候就是先有鸡还是先有蛋的问题,所以我们将接口设计成静态的。在这里插入图片描述解决了再堆上创建对象的问题,但是又有可能通过构造和赋值,再栈上创建对象,所以需要防拷贝在这里插入图片描述
这样就解决问题了。

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

这个设计理念和上面哪个很相似
我们需要将构造函数私有化,这样才能保证都创建不了对象,然后提供一个接口。

class stackonly
{
public:
	static stackonly creatobj()//通过类名去调用函数。
	{
		stackonly st;
		return st;
	}
private:
	stackonly(){}

	//防拷贝
	//stackonly(const stackonly& h) = delete;
	//stackonly& operator=(const stackonly& h) = delete;

	//将new变成私有的
	void* operator new(size_t size){}
};
int main()
{
	stackonly s1=stackonly::creatobj();//1
	stackonly* s2 = new stackonly(s1);//2
	return 0;
}

再没有防拷贝和new私有化的前提下,我们的代码2是可以通过的,所以我们添加了防拷贝,或者new私有化,原因是new->operator new+构造,封其中一个就可以了。
但是我们栈区对象给栈区对象拷贝构造和赋值就不行了,所以我们不封防拷贝

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

C++98的方式

// C++98中构造函数私有化,派生类中调不到基类的构造函数。则无法继承
class NonInherit
{
public:
 static NonInherit GetInstance()
 {
 return NonInherit();
 }
private:
 NonInherit()
 {}
};

c++11的方式:

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

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

这是我们这节重点介绍的,而且他很重要,他又两种模式–饿汉模式、懒汉模式

设计模式:
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的
总结。为什么会产生设计模式这样的东西呢?就像人类历史发展会产生兵法。最开始部落之间打
仗时都是人拼人的对砍。后来春秋战国时期,七国之间经常打仗,就发现打仗也是有套路的,后
来孙子就总结出了《孙子兵法》。孙子兵法也是类似。
使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模
式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。

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

5.1饿汉模式


class Singleton
{
public:
	//设计成静态的原因是通过类名去调用函数,因为进行了防拷贝,所以需要传引用
	static Singleton& GetInstance()
	{
		return _st;
	}

	//对单例对象的部分操作。
	void add(pair<string,string>& kv)
	{
		_dict[kv.first] = kv.second;
	}
	void print()
	{
		for (auto& e : _dict)
		{
			cout << e.first << ":" << e.second << endl;
		}
		cout << endl;
	}
private:
	//1.构造函数私有化,这样都不能创建对象,所以要提供一个接口
	Singleton(){}

	map<string, string> _dict;

	static Singleton _st;//这个就是整个程序的单例对象,所以类共有的
	// Singleton _st这样不行,这时候_st属于类里面,会嵌套。


	//防拷贝,原因只能创建一个对象,再接口返回的时候要返回引用
	Singleton(const Singleton& s) = delete;
	Singleton& operator=(const Singleton& s) = delete;
};

Singleton Singleton::_st;//静态成员变量类里面声明,类外名定义,这个定义还是可以访问到类里面的内容
							// 在程序入口之前就完成单例对象的初始化

上面代码已经有注释,我们来验证一下,我们来看看里面每次调用函数的接口返回的对象是不是同一个:
在这里插入图片描述

我们只能通过调用接口来创建对象,而每次调用都是同一个,那么这样就设计出了一个单例对象,这里巧妙的利用静态成员函数只有一份的特点,接下来验证一下操作:
在这里插入图片描述
至此我们的单例模式就设计出来了


饿汉模式的缺点
(1)单例对象的创建是再main函数之前的,万一单例对象很大,很多,那么启动时间就很长
(2)万一有两个单例对象互相有依赖关系,就不行了。
(3)不管你用不用他肯定都会创建的。

有了上面的缺点,我们有下面的一种模式,懒汉模式。
他再使用的时候才创建对象,他先创建一个静态指针,就算就main函数之前创建也就一个指针的大小。

namespace lazy
{
	class Singleton
	{
	public:
		//设计成静态的原因是通过类名去调用函数,因为进行了防拷贝,所以需要传引用
		static Singleton& GetInstance()
		{
			if (_st == nullptr)
			{
				_st=new Singleton;
			}
			return *_st;
		}

		//对单例对象的部分操作。
		void add(const pair<string, string>& kv)
		{
			_dict[kv.first] = kv.second;
		}
		void print()
		{
			for (auto& e : _dict)
			{
				cout << e.first << ":" << e.second << endl;
			}
			cout << endl;
		}
		
	private:
		//1.构造函数私有化,这样都不能创建对象,所以要提供一个接口
		Singleton() {}

		map<string, string> _dict;

		static Singleton* _st;//这个就是整个程序的单例对象,所以类共有的
		// Singleton _st这样不行,这时候_st属于类里面,会嵌套。


		//防拷贝,原因只能创建一个对象,再接口返回的时候要返回引用
		Singleton(const Singleton& s) = delete;
		Singleton& operator=(const Singleton& s) = delete;
	};

	Singleton* Singleton::_st=nullptr;//静态成员变量类里面声明,类外名定义,这个定义还是可以访问到类里面的内容
}

在这里插入图片描述
再懒汉模式里面因为我们是手动new出来的,所以我们需要进行释放,正常情况,单例对象都是随着程序解释自动释放,但是不干保证有的时候再中间就需要释放去做持久化操作,将数据写进文件等等。拿这样我们怎么去设计呢??

第一种方法:
再类里面添加这个。

		static void DelInstance()
		{
			if (_st)
			{
				delete _st;//这个delete会调用析构函数
				_st = nullptr;
			}
		}

		~Singleton()//自购函数只有程序结束后会自动调用,不能显示的调用,通过接口去调用他。
		{
			cout << "~Singleton()" << endl;
				// map数据写到文件中
			FILE* fin = fopen("map.txt", "w");
			for (auto& e : _dict)
			{
				fputs(e.first.c_str(), fin);
				fputs(":", fin);
				fputs(e.second.c_str(), fin);
				fputs("\n", fin);
			}
		}

在这里插入图片描述
这种方法值适用于单例对象少,释放地方少,如果道理对象多,释放位置多,就麻烦了,这时候我们有第二种方法:

5.2懒汉模式

	
namespace lazy
{
	class Singleton
	{
	public:
		//设计成静态的原因是通过类名去调用函数,因为进行了防拷贝,所以需要传引用
		static Singleton& GetInstance()
		{
			if (_st == nullptr)
			{
				_st=new Singleton;
			}
			return *_st;
		}

		//对单例对象的部分操作。
		void add(const pair<string, string>& kv)
		{
			_dict[kv.first] = kv.second;
		}
		void print()
		{
			for (auto& e : _dict)
			{
				cout << e.first << ":" << e.second << endl;
			}
			cout << endl;
		}

		static void DelInstance()
		{
			if (_st)
			{
				delete _st;//这个delete会调用析构函数
				_st = nullptr;
			}
		}

		~Singleton()//析构函数只有程序结束后会自动调用,不能显示的调用,通过接口去调用他。
		{
			cout << "~Singleton()" << endl;
			// map数据写到文件中
			FILE* fin = fopen("map.txt", "w");
			for (auto& e : _dict)
			{
				fputs(e.first.c_str(), fin);
				fputs(":", fin);
				fputs(e.second.c_str(), fin);
				fputs("\n", fin);
			}
		}

		class GC
		{
		public:
			~GC()
			{
				lazy::Singleton::DelInstance();
			}
		};
	private:
		//1.构造函数私有化,这样都不能创建对象,所以要提供一个接口
		Singleton() {}

		map<string, string> _dict;

		static Singleton* _st;//这个就是整个程序的单例对象,所以类共有的
		// Singleton _st这样不行,这时候_st属于类里面,会嵌套。


		//防拷贝,原因只能创建一个对象,再接口返回的时候要返回引用
		Singleton(const Singleton& s) = delete;
		Singleton& operator=(const Singleton& s) = delete;

		static GC _gc;
	};

	Singleton* Singleton::_st=nullptr;//静态成员变量类里面声明,类外名定义,这个定义还是可以访问到类里面的内容
	Singleton::GC Singleton::_gc;
}

在这里插入图片描述

我们发现不使用我写的两种方法,最后都无法调用到析构函数,第一种方法是可以再任意位置进行释放,第二种方式是防止程序结束后忘记释放,这样设计就可以直接自动释放了。

六、总结

至此我们的特殊类的设计就讲解完毕了,博主讲解的都是简单的特殊类,到实际开发的时候,类的设计就很复杂,大家先知道大致模式旧可以了,我们平时用到也少。但是要了解,别一点都没有听过。我们这篇的讲解旧到此结束了,我们下篇再见。

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

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

相关文章

【代码随想录】算法训练营 第八天 第四章 字符串 Part 1

344. 反转字符串 题目 思路 我的思路是&#xff0c;用双指针&#xff0c;一个指左&#xff0c;一个指右&#xff0c;循环互换即可。 代码随想录的更简单精妙&#xff0c;直接用一个for循环搞定&#xff0c;里面用swap来互换。 代码 我的解法 class Solution { public:voi…

【IEEE】1区TOP仅1个月见刊(附IEEE旗下SCI实时影响因子汇总)

IEEE出版的SCI期刊有近200本&#xff0c;本期我们主要关注IEEE旗下被SCIE收录期刊的实时IF2023&#xff0c;所有期刊按照字母顺序排列。为方便对比&#xff0c;我们还给出了IF2022&#xff08;即今年6月公布的最新影响因子&#xff09;&#xff0c;供大家参考。 备注&#xff…

达索智能制造解决方案,敏捷电芯制造如何赋能企业竞争力 | 百世慧®

敏捷电芯制造赋能企业竞争力 全球电池市场正在快速扩大&#xff0c;为制造商带来巨大商机。 锂电行业的智能制造如何应用&#xff1f; 电池制造业的市场趋势是什么&#xff1f; 电池制造商面临哪些挑战&#xff1f; 特别是电池电芯制造方面&#xff0c;如何克服挑战获得竞…

阿里巴巴店铺所有商品数据接口及店铺商品数据分析

获取阿里巴巴店铺所有商品数据的接口是阿里巴巴开放平台提供的接口&#xff0c;通过该接口可以获取店铺所有商品数据。 通过阿里巴巴开放平台接口获取店铺所有商品数据的方法如下&#xff1a; 在开放平台注册成为开发者并创建一个应用&#xff0c;获取到所需的 App Key 和 Ap…

【华为认证超全科普帖】

华为认证是由华为基于“平台生态”战略&#xff0c;围绕“云-管-端”协同的新ICT技术架构&#xff0c;打造的业界覆盖ICT领域蕞广的认证体系。在信息和通信技术行业具有较高的含金量。 华为认证分为3个等级: HCIA (初级)&#xff1a;华为认证ICT工程师 HCIP (中级)&#xff1…

Pyside6 QMessageBox

Pyside6 QMessageBox QMessageBox使用5种基本消息自定义消息框QMessageBox标准按钮程序界面程序主程序 QMessageBox是一种通用的弹出式对话框&#xff0c;用于显示提示消息&#xff0c;允许用户点击不同的消息框按钮做出不同的判断。Pyside6提供了QMessageBox的操作函数&#x…

如何把Elasticsearch中的数据导出为CSV格式的文件

前言| 本文结合用户实际需求用按照数据量从小到大的提供三种方式从ES中将数据导出成CSV形式。本文将重点介Kibana/Elasticsearch高效导出的插件、工具集&#xff0c;通过本文你可以了解如下信息&#xff1a; 1&#xff0c;从kibana导出数据到csv文件 2&#xff0c;logstash导…

【EI会议征稿】第七届智能制造与自动化国际学术会议(IMA 2024)

第七届智能制造与自动化国际学术会议&#xff08;IMA 2024&#xff09; 2024 7th International Conference on Intelligent Manufacturing and Automation 第七届智能制造与自动化国际学术会议&#xff08;IMA 2024&#xff09;定于2024年1月12-14日在长沙隆重举行。会议主要…

自动注入@RequiredArgsConstructor

Autowired有波浪线&#xff0c;显示推荐使用构造器注入的方式。 但是以后需要自动注入的对象很多&#xff0c;写这么多构造函数代码会很长&#xff0c;可以在类上面加lombok中的RequiredArgsConstructor&#xff0c;表示必备参数的构造函数&#xff0c;给加final的成员变量生成…

使用Docker快速搭建Redis主从复制

目录 一、前言二、拉取Redis镜像三、创建挂载目录和添加配置文件3.1、主节点(6379)3.2、从节点(6380)3.3、从节点(6381) 四、启动Redis容器4.1、主节点(6379)4.2、从节点(6380)4.3、从节点(6381)4.4、启动命令参数介绍 五、查看各节点主从信息5.1、主节点(6379)5.2、从节点(638…

淘宝API访问入口未授权怎么解决?

没有授权应该是读取数据失败或是网络传输不稳定。 API的主要功能是提供应用程序与开发人员以访问一组例程的能力&#xff0c;而又无需访问源码&#xff0c;或理解内部工作机制的细节。提供API所定义的功能的软件称作此API的实现。API是一种接口&#xff0c;故而是一种抽象。 …

火山引擎实时、低延时拥塞控制算法的优化实践

摘要 火山引擎智能拥塞控制算法 VICC&#xff08;Volcano Intelligent Congestion Control&#xff09;是一种自适应的拥塞控制算法&#xff0c;旨在解决全球不同网络环境下&#xff0c;不同音视频应用对带宽利用率和延时的差异化要求。它结合了传统拥塞控制算法&#xff08;如…

YCSB and TPC-C on MySQL(避免重复load)

一、编译安装MySQL 下载mysql5.7.28源码 https://downloads.mysql.com/archives/community/ Select Operating System 选择 Source Code Select OS version 选择 All Operating Systems 选择带有boost的版本 安装系统包 apt -y install make cmake gcc g perl bison libai…

网站批量替换关键词方法

注意替换操作之前先对文件做好备份 1.下载http://downinfo.myhostadmin.net/ultrareplace5.02.rar 解压出来,运行UltraReplace.exe 2.点击菜单栏中的配置&#xff0c;全选所有文件类型,或者根据自己的需求选择部分,如htm、html、php、asp等 3.若替换单个文件,点击文件,若是要…

月薪15-25k,急招Web安全研究员

更多岗位招聘信息 请wx搜索【知了内推】小程序

CentOS 系统安装和使用Docker服务

系统环境 使用下面的命令&#xff0c;可以查看CentOS系统的版本。 lsb_release -a结果&#xff1a; 说明我的系统是7.9.2009版本的 安装Docker服务 依次执行下面的指令&#xff1a; yum install -y yum-utilsyum install -y docker即可安装docker服务 如果这样安装不成功…

python+selenium的web自动化上传操作的实现

一、关于上传操作 上传有两种情况&#xff1a; 如果是input可以直接输入路径的&#xff0c;那么直接使用send_keys(文件路径)输入路径即可&#xff1b; 非input标签的上传&#xff0c;则需要借助第三方工具&#xff1a;第三方库 pywin32、第三方工具pyautogui等等。 那这里…

Android问题笔记 - ViewPager嵌套RecyclerView,降低ViewPager灵敏度

点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册点击跳转>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&…