C++——特殊类设计

目录

前言

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

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

2.1 思路一:构造函数私有

2.2 思路二,析构函数私有

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

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

4.1 关于设计模式

4.2 单例模式

4.3 饿汉模式

4.4 懒汉模式


前言

C++的类是C++这门面向对象语言的精华所在,C++的类设计在众多OO语言中也是非常具有代表性的存在。所以,原本的类功能已经可以满足我们大部分的需求,但是随着编程语言的不断发展和实际应用的持续复杂,类原本的功能可能会有一部分失效或缺陷。

所以就有了特殊类设计,通过设计特殊的类来应对特殊的各种情况。正所谓对症下药。下面给出了部分特殊类设计

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

不能被拷贝的类我们在智能指针的unique_ptr已经初步认识过了,要想一个类不能被拷贝,只要想办法把它的拷贝构造和赋值重载干掉即可,如下代码:C++98和C++11的处理方式不同

class BanCopy
{//C++98的处理方式
private:/*BanCopy(const BanCopy&);BanCopy& operator=(const BanCopy&);*/
public:BanCopy(int a = 0):_a(a){cout << "BanCopy()" << endl;}~BanCopy(){cout << "~BanCopy" << endl;}//C++11的处理方式BanCopy(const BanCopy&) = delete;BanCopy& operator=(const BanCopy&) = delete;
private:int _a;
};int main()
{BanCopy a(1);BanCopy b(a);
}

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

2.1 思路一:构造函数私有

class HeapOnly
{
public://提供一个公有的获取对象的方式,对象控制是new出来的static HeapOnly* CreateObj(){return new HeapOnly;}//防拷贝HeapOnly(const HeapOnly& hp) = delete;HeapOnly& operator=(const HeapOnly& hp) = delete;
private:HeapOnly():_a(0){}
private:int _a;
};
//构造函数私有
void main3()
{/*HeapOnly hp1;static HeapOnly hp2;*///HeapOnly* hp3 = CreateObj();//上面这一条语句是先有鸡还是先有蛋的问题,我们可以通过CreateObj来创建对象,但是我们只有先创建对象才能调用CreateObj//把CreateObj定义成static就可以了HeapOnly* hp3 = HeapOnly::CreateObj();delete hp3;//HeapOnly* copy(hp3);
}

2.2 思路二,析构函数私有

class HeapOnly
{
public:/*static void Delete(HeapOnly* ptr){delete ptr;}*///两种方式都可以void Delete(){delete this;}
private:~HeapOnly(){cout << "~HeapOnly" << endl;}
private:int _a;
};//析构函数私有
void main()
{/*HeapOnly hp1;static HeapOnly hp2;*/HeapOnly* ptr = new HeapOnly;//HeapOnly::Delete(ptr);ptr->Delete();
}

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

class StackOnly
{
public:static StackOnly CreateObj(){StackOnly st;return st;}// 不能防拷贝//StackOnly(const StackOnly& st) = delete;//StackOnly& operator=(const StackOnly& st) = delete;void* operator new(size_t n) = delete;
private:// 构造函数私有StackOnly():_a(0){}
private:int _a;
};void main4()
{StackOnly st1 = StackOnly::CreateObj();//拷贝构造static StackOnly copy2(st1);//本来不能拷贝的,用防拷贝,但是这样又会限制上面的CreateObj,不好处理,算是一个小缺陷//StackOnly* copy = new StackOnly(st1); 要防止栈上的数据拷贝到堆上可以把new禁掉
}

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

4.1 关于设计模式

设计模式(Design Pattern)是一套被反复使用,多数人知晓的,经过分类的,代码设计经验的总结。而它产生的原因就好比我们中国古代兵法的产生,最开始各部落之间打仗就是拼人数,无技术含量的对砍,后来春秋战国后,各国也经常打仗,后来发现打仗也是有套路的,后来就有了《孙子兵法》

而使用设计模式的目的:提高代码可重用性,和可理解性,保证代码可靠性。设计模式使代码真正工程化,是软件工程的基石。

4.2 单例模式

一个类只能创建一个对象,即单例模式。该模式保证系统中该类只有一个实例化对象,并提供一个访问它的全局访问点,并且该实例被所有程序模块共享。

简单来说:保证一些数据(一个进程中)全局只有唯一一份,并且方便访问
①把这些数据放进一个类里面,把这个类设计出单例类
②封死构造和拷贝,提供一个static公有获取单例对象地函数
③如何创建单例对象,饿汉和懒汉

单例new对象释放问题:
①一般情况下,单例对象不需要释放的。因为一般整个程序运行期间都可能会用它。
单例对象在进程正常结束后,也会资源释放。
②有些特殊场景需要释放

4.3 饿汉模式

在main函数开始之前就创建出唯一对象

优点:代码简单,并且无线程安全问题,因为是在main函数之前创建的

缺点:

①一个程序中如果有多个单例需要被创建,并且这多个单例有创建顺序时,饿汉无法控制创建顺序

②饿汉单例类如果初始化任务多,会影响程序启动速度

class Singleton1
{
public://要保证每次获取的对象都是同一个对象,自己定义一个静态的自己类型的对象或指针static Singleton1* GetInstance(){return _pinst;}void Add(const string& str){_mtx.lock();_v.push_back(str);_mtx.unlock();}void Print(){_mtx.lock();for (auto& e : _v){cout << e << endl;;}cout << endl;_mtx.unlock();}
private://构造函数私有化,是为了限制在类外面随意创建对象Singleton1(){}Singleton1(const Singleton1& s) = delete;Singleton1& operator=(const Singleton1& s) = delete;
private:mutex _mtx;vector<string> _v;//static Singleton _inst;//声明static Singleton1* _pinst; // 声明
};//静态的必须在类外面初始化
//Singleton1 Singleton1::_inst = new Singleton1;
Singleton1* Singleton1::_pinst = new Singleton1;//线程安全地往里面添加数据
void main()
{srand(time(0));int n = 100;thread t1([n]() {for (size_t i = 0; i < n; i++){Singleton1::GetInstance()->Add("t1线程:" + to_string(rand()));}});thread t2([n]() {for (size_t i = 0; i < n; i++){Singleton1::GetInstance()->Add("t2线程:" + to_string(rand()));}});t1.join();t2.join();Singleton1::GetInstance()->Print();
}

4.4 懒汉模式

饿汉模式有程序启动时间增长的问题,所以我们可以用懒汉模式,它表示当我们第一次要使用对象时再创建实例对象

优点:①不需要控制创建顺序  ②不影响启动速度

缺点:①代码实现相比饿汉更复杂,这个在下面的代码中会深有体会  ②线程安全问题要处理好,因为如果不对临界区做保护会造成很严重的后果

class Singleton2
{
public:static Singleton2* GetInstance(){//每次获取对象都要加锁解锁,但是我们只需要第一次new地时候加锁解锁//双检查加锁if (_pinst == nullptr) //这个时为了提供效率,不需要每次获取单例都加锁解锁{_imtx.lock();if (_pinst == nullptr) //这个才是保证线程安全和只new一次{_pinst = new Singleton2;}_imtx.unlock();}return _pinst;}void Add(const string& str){//添加数据时要保证线程安全_vmtx.lock();_v.push_back(str);_vmtx.unlock();}void Print(){_vmtx.lock();for (auto& e : _v){cout << e << endl;;}cout << endl;_vmtx.unlock();}class CGarbo{public:~CGarbo(){if (_pinst){delete _pinst;_pinst = nullptr;}}};//上面那个是自动释放,我们也可以显示手动释放static void DelInstance(){_imtx.lock();if (_pinst){delete _pinst;_pinst = nullptr;}_imtx.unlock();}private://构造函数私有化,还有防拷贝Singleton2(){}Singleton2(const Singleton2& s) = delete;Singleton2& operator=(const Singleton2& s) = delete;
private:mutex _vmtx;vector<string> _v;static Singleton2* _pinst;//声明static mutex _imtx;
};//定义
Singleton2* Singleton2::_pinst = nullptr;
mutex Singleton2::_imtx;//回收对象,main函数结构后,他会调用析构函数,就会释放单例对象
static Singleton2::CGarbo gc;void main6()
{srand(time(0));int n = 100;thread t1([n]() {for (size_t i = 0; i < n; i++){Singleton2::GetInstance()->Add("t1线程:" + to_string(rand()));}});thread t2([n]() {for (size_t i = 0; i < n; i++){Singleton2::GetInstance()->Add("t2线程:" + to_string(rand()));}});t1.join();t2.join();Singleton2::GetInstance()->Print();
}

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

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

相关文章

Cortex-M7 内存映射

1 前言 如图1所示&#xff0c; Cortex-M7最大支持4GB的内存寻址&#xff0c;并对内存映射(memory map)做了初步的规定&#xff0c;将整个内存空间划分为了多个内存区域(region)。每个内存区域有着既定的内存类型(memory type)和内存属性(memory attribute)&#xff0c;这两者决…

使用 msys2 sshd为 windows 搭建 ssh 服务器

文章目录 概要整体架构流程技术名词解释MSYS2openSSH服务器 技术细节安装 MSYS2 环境安装openSSH配置、启动SSH 小结和扩展 概要 SSH服务器在Linux下的搭建一般的文章讨论的比较多了。在Windows下&#xff0c;我们常用Windows的Linux子系统来搭建ssh服务器。那有没有更好更简洁…

SV学习笔记(五)

文章目录 线程的使用程序和模块什么是线程线程的概念澄清 线程的控制fork并行线程语句块fork…joinfork…join_any等待所有衍生线程停止单个线程停止多个线程停止被多次调用的任务 线程的通信写在前面event事件通知的需求semaphore旗语mailbox信箱三种通信的比较和应用 参考资料…

无人机/飞控--ArduPilot、PX4学习记录(4)

这是一篇碎碎念&#xff0c;零零碎碎的记录了小组准备竞赛的过程&#xff0c;写的挺乱&#xff0c;仅供本人记录学习历程和参考。 本章主要完成的目标&#xff1a;调试地面站 GPS、加速度校准&#xff1b;试飞并炸机 目录 地面站(QGC)安装(*未完成) 地面站Mission Planner 1.…

深度学习理论基础(六)Transformer多头注意力机制

目录 一、自定义多头注意力机制1. 缩放点积注意力&#xff08;Scaled Dot-Product Attention&#xff09;● 计算公式● 原理 2. 多头注意力机制框图● 具体代码 二、pytorch中的子注意力机制模块 深度学习中的注意力机制&#xff08;Attention Mechanism&#xff09;是一种模仿…

Pillow教程09:图片格式(png,jpg,ico等)批量转换+批量修改图片尺寸

---------------Pillow教程集合--------------- Python项目18&#xff1a;使用Pillow模块&#xff0c;随机生成4位数的图片验证码 Python教程93&#xff1a;初识Pillow模块&#xff08;创建Image对象查看属性图片的保存与缩放&#xff09; Pillow教程02&#xff1a;图片的裁…

rust 面向对象编程特性、模式与模式匹配、高级特征

面向对象编程OOP 学习了结构体、枚举&#xff0c;它们可以包含自定义数据字段&#xff0c;也可以定义内部方法&#xff0c;它们提供了与对象相同的功能。 面向对象的四大特征&#xff1a;封装、继承、多态 通过pub标记为公有的结构体&#xff0c;在其他模块中可以访问使用这…

Java数据结构队列

队列(Queue) 概念 队列的使用 注意&#xff1a;Queue是个接口&#xff0c;在实例化时必须实例化LinkedList的对象&#xff0c;因为LinkedList实现了Queue接口。 import java.util.LinkedList; import java.util.Queue;public class Test {public static void main(String[]…

敏感信息泄露漏洞

法律声明 参与培训需要遵守国家法律法规&#xff0c;相关知识只做技术研究&#xff0c;请勿用于违法用途&#xff0c;造成任何后果自负与本人无关。 中华人民共和国网络安全法&#xff08;2017年6月1日起施行&#xff09; 第二十二条 任何个人和组织不得从事入侵他人网络、干扰…

基于SpringBoot+Vue的OA管理系统

一、项目背景介绍&#xff1a; 办公自动化&#xff08;Office Automation&#xff0c;简称OA&#xff09;&#xff0c;是将计算机、通信等现代化技术运用到传统办公方式&#xff0c;进而形成的一种新型办公方式。办公自动化利用现代化设备和信息化技术&#xff0c;代替办公人员…

LangChain-09 Query SQL DB With RUN GPT 查询数据库 并 执行SQL 返回结果

安装依赖 pip install --upgrade --quiet langchain-core langchain-community langchain-openai编写代码 from langchain_core.prompts import ChatPromptTemplate from langchain_community.utilities import SQLDatabase from langchain_core.output_parsers import StrO…

python 02字符串

字符串可能是用到最多的数据类型了&#xff0c;所有标准序列操作&#xff08;索引、切片、乘法、成员资格检查、长度、最小值和最大值&#xff09;都适用于字符串 但别忘了字符串是不可变的&#xff0c;因此所有的元素赋值和切片赋值都是非法的。 1.居中效果 默认为空格 可…