14.C++ 特殊类与设计模式

特殊类设计

  • 1. 不能被拷贝的类
  • 2. 只能在堆上创建对象的类
  • 3. 只能在栈上创建对象的类
  • 4. 设计一个类,不能被继承
  • 5. 单例模式
    • 概念
    • 饿汉模式
    • 懒汉模式
  • 6. 模版方法模式
  • 7. 工厂模式
  • 8. 观察者模式

1. 不能被拷贝的类

拷贝只会出现在两个场景中:拷贝构造和拷贝赋值。因此让该类无法调用这两个函数即可(两种方法)

  • 令这两个函数私有
  • 使用C++11关键字delete
class A
{
public:A(){}A(const A& a) = delete;  //删除函数A& operator=(const A& a) = delete;
private://A(const A& a) {}   //私有化//A& operator=(const A& a) {}
};

2. 只能在堆上创建对象的类

  1. 构造函数私有,拷贝构造私有
  2. 提供一个静态成员函数,在此函数中完成在堆上创建对象
class A
{
public:static A* CreateFronHeap(){return new A;}
private:A(const A& a) {}   //私有化A(){}
};int main()
{A* a = A::CreateFronHeap();cout << a << endl;return 0;
}

3. 只能在栈上创建对象的类

  1. 把operator new和delete这些禁用掉
  2. 提供一个静态成员函数,在此函数中完成在栈上创建对象
  • 以下为最初设想的逻辑
class A
{
public:static A CreateFronStack(){return A();}void* operator new(size_t size) = delete;void operator delete(void* ptr) = delete;void* operator new[](size_t size) = delete;void operator delete[](void* ptr) = delete;
};int main()
{A a = A::CreateFronStack();cout << &a << endl;return 0;
}

但尽管如此,由于构造函数是公有,所以还是有方法让这个类型在堆上创建(创建个新类,让A做成员)

class foo
{
public:A a;
};
int main()
{A a = A::CreateFronStack();cout << &a << endl;foo* f = new foo;cout << f << endl;cout << &f->a << endl;return 0;
}

因此,构造函数必须是私有(但是静态成员函数无法访问类内部成员);再者根据单例模式的灵感,可以变相的通过一个静态变量调用成员函数再调用构造函数

class A
{
public:static A CreateFronStack(){return _self.Create();}A Create(){return A();}void* operator new(size_t size) = delete;void operator delete(void* ptr) = delete;void* operator new[](size_t size) = delete;void operator delete[](void* ptr) = delete;
private:A(){}static A _self;
};
A A::_self = A(); //定义静态变量来调用成员函数int main()
{A a = A::CreateFronStack();A b = A::CreateFronStack();cout << &a << endl;cout << &b << endl;return 0;
}

4. 设计一个类,不能被继承

  1. 构造函数私有
class A
{
private:A(){}
};
  1. C++11的final关键字
class A final
{};
class B : public A //提示:不能将A作为基类
{};

5. 单例模式

概念

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

饿汉模式

程序启动时就创建一个唯一的实例对象
优点:简单
缺点:可能导致进程启动慢,且如果有多个单例对象实例启动顺序不确定

class Single
{
public:static Single* GetInstance(){return &_sIns;}
private:Single(){}Single(const Single& sl) = delete;Single& operator=(const Single& sl) = delete;static Single _sIns;
};
Single Single::_sIns; //在程序入口之前就完成单例对象实例化int main()
{Single* sl = Single::GetInstance();return 0;
}

懒汉模式

程序第一次调用时才实例化对象
优点:进程启动无负载,多个单例实例启动顺序自由控制
缺点:复杂

class Single
{
public:static Single* GetInstance(){if (_sIns == nullptr) //如果单例不在,再加锁{lock_guard<mutex> lock1(_mtx);if (_sIns == nullptr) //只有一个线程会进来,其他线程阻塞在lock{_sIns.reset(new Single());}}return _sIns.get();}
private:Single(){}Single(const Single& sl) = delete;Single& operator=(const Single& sl) = delete;static unique_ptr<Single> _sIns; //单例对象static mutex _mtx; //单例对象创建时需要锁
};
unique_ptr<Single> Single::_sIns = nullptr;
mutex Single::_mtx;int main()
{Single* sl = Single::GetInstance();return 0;
}

6. 模版方法模式

模版方法定义了一个大致的框架(父类),后续继承的子类可以重新定义这个框架的步骤。
如下代码

  • 定义了做作业的父类,他只提供做作业的总步骤(DoMyHomeWork)模版方法,和下面的Write、Check、Submit都是抽象方法(纯虚函数),由子类自行实现。具体的子类ChineseHw和MathHw来实现做不同作业的差异步骤
  • 调用函数时可以使用多态
  • 父类属于抽象类,无法实例化对象
class Homework
{
public:void DoMyHomeWork() //做作业的整个步骤,但是做什么内容取决于子类{Write();Check();Submit();}virtual ~Homework(){}
public:virtual void Write() = 0;  //写作业virtual void Check() = 0;  //检查作业virtual void Submit() = 0; //提交作业
};class ChineseHw : public Homework
{
public:void Write() override{cout << "写语文作业" << endl;}void Check() override{cout << "检查语文作业" << endl;}void Submit() override{cout << "提交语文作业" << endl;}~ChineseHw(){cout << "析构语文作业对象" << endl;}
};class MathHw : public Homework
{
public:void Write() override{cout << "写数学作业" << endl;}void Check() override{cout << "检查数学作业" << endl;}void Submit() override{cout << "提交数学作业" << endl;}~MathHw() {cout << "析构数学作业对象" << endl;}
};int main()
{unique_ptr<Homework> h1(new ChineseHw);unique_ptr<Homework> h2(new MathHw);h1->DoMyHomeWork();h2->DoMyHomeWork();return 0;
}

7. 工厂模式

工厂类主要用于创建产品对象,对象的创建和使用分离,使得代码结构清晰。不需要了解产品的具体过程,只需要关系产品的使用

class Base
{
public:virtual void Print() = 0;virtual ~Base(){}
};class A : public Base
{
public:void Print() override{cout << "I am A" << endl;}~A() { cout << "~A" << endl; };
};
class B : public Base
{
public:void Print() override{cout << "I am B" << endl;}~B() { cout << "~B" << endl; };
};class Factory //工厂
{
public:static Base* CreateA() { return new A(); };static Base* CreateB() { return new B(); };
};
int main()
{Base* b1 = Factory::CreateA();Base* b2 = Factory::CreateB();b1->Print();b2->Print();delete b1;delete b2;return 0;
}

8. 观察者模式

观察者模式定义了对象之间一对多依赖关系,当一个被观察对象状态发生改变时,其他观察者对象会得到通知并自动更新

//==================== 观察者抽象类 ====================//
class Observer
{
public:virtual void update(const string& news) = 0;
};
//学生类
class Student : public Observer
{
private:string name;
public:Student(const string& n):name(n){}void update(const string& news){cout << "[Student: " << name << " ] get a news: " << news << endl;}
};
//老师类
class Teacher : public Observer
{
private:string name;
public:Teacher(const string& n) :name(n){}void update(const string& news){cout << "[Teacher: " << name << " ] get a news: " << news << endl;}
};
//==================== 被观察者抽象类 ====================//
class Subject
{
protected:vector<Observer*> _observers; //观察者的集合
public:virtual void attach(Observer* obs) //添加观察者{_observers.push_back(obs);}virtual void detach(Observer* obs)  //删除观察者{for (int i = 0; i < _observers.size(); i++){if (obs == _observers[i]){_observers.erase(_observers.begin() + i);break;}}}virtual void notify(const string& news) = 0; //通知观察者
};
//学校机构类
class SchoolAgency : public Subject
{
public:void notify(const string& news) override{for (int i = 0; i < _observers.size(); i++){_observers[i]->update(news);}}
};
int main()
{SchoolAgency agency;Student st1("张三");Teacher tc1("李四");agency.attach(&st1);agency.attach(&tc1);agency.notify("今天天气小雨,建议带伞。");return 0;
}

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

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

相关文章

Python将Word文档转为PDF

将word转pdf&#xff0c;只能使用办公工具&#xff0c;但是这些工具大都是收费。因此想用python 将word转pdf,发现很好用特此记录下。方法一&#xff1a;使用docx2pdf模块将docx文件转为pdf 要实现这样的功能&#xff0c;需要用到的就是 docx2pdf 这个python第三方库。对于doc…

无惧任天堂的法律威胁:Switch模拟器Ryujinx v1.2.72版发布

此前任天堂向多个提供 Nintendo Switch 模拟器项目发送律师函甚至直接起诉&#xff0c;要求这些项目立即停止更新、删除以及向任天堂提供经济赔偿。其中 Ryujinx 项目已经在 2024 年 10 月 1 日因任天堂的法律威胁而放弃项目&#xff0c;不过很快就有分叉版本出现&#xff0c;这…

JavaWeb——Web入门(6/9)-HTTP协议:协议解析(客户端的 HTTP 协议解析、服务端的 HTTP 协议解析、Web服务器的作用)

目录 概述 客户端的 HTTP 协议解析 服务端的 HTTP 协议解析 Web服务器的作用 概述 了解完 HTTP 协议的请求数据格式以及响应数据格式之后&#xff0c;接下来我们来讲了解 HTTP 协议的解析。 HTTP 协议的解析分为客户端和服务端两个部分&#xff0c;客户端浏览器中内置了解…

操作系统-实验报告单(2)

目录 1 实验目标 2 实验工具 3 实验内容、实验步骤及实验结果 一、自定义操作系统并启动 1. 最简单操作系统的编写并生成镜像文件 2.虚拟机启动操作系统 【思考题&#xff1a;1、仔细阅读helloos.nas&#xff0c;结合操作系统启动过程尝试分析它的作用&#xff1b;2、若…

城镇住房保障:SpringBoot系统优化技巧

3系统分析 3.1可行性分析 通过对本城镇保障性住房管理系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本城镇保障性住房管理系统采用SSM框架&#xff0c;JA…

FlyMcu串口下载STLink Utility

1、FlyMcu FlyMcu串口下载&#xff0c;同STC-ISP&#xff08;51单片机下载&#xff09;。 使用步骤&#xff1a; 1、STM32的USART1通过串口转usb连接到电脑 2、通过keil生成Hex、bin文件 生成bin、hex文件可参考 keil生成bin文件&#xff08;简单&#xff09;-CSDN博客 创建…

aws(学习笔记第十课) 对AWS的EBS如何备份(snapshot)以及使用snapshot恢复数据,AWS实例存储

aws(学习笔记第十课) 对AWS的EBS如何备份&#xff08;snapshot&#xff09;以及使用snapshot&#xff0c;AWS实例存储 学习内容&#xff1a; 对AWS的EBS如何备份AWS实例存储EBS和实例存储的不足 1. 对AWS的EBS如何备份&#xff08;snapshot&#xff09;以及使用snapshot恢复数…

论文2—《基于柔顺控制的智能神经导航手术机器人系统设计》文献阅读分析报告

论文报告&#xff1a;基于卷积神经网络的手术机器人控制系统设计 摘要 本研究针对机器人辅助微创手术中定向障碍和缺乏导航信息的问题&#xff0c;设计了一种智能控制导航手术机器人系统。该系统采用可靠和安全的定位技术、7自由度机械臂以及避免关节角度限制的逆运动学控制策…

《数据结构与算法》二叉树基础OJ练习

二叉树的基础知识详见&#xff1a;《数据结构与算法》二叉树-CSDN博客 1 单值二叉树 思路 我们把树分成当前树&#xff08;用根和左孩子还有右孩子进行比较&#xff0c;如果左孩子或者右孩子为空那就不比了&#xff0c;如果左右孩子或者其中一个存在就比较&#xff0c;相等就是…

栈和队列(C 语言)

目录 一、栈1. 栈的概念2. 栈的结构3. 栈的实现思路4. 栈的实现代码 二、队列1. 队列的概念2. 队列的结构3. 队列的实现思路4. 队列的实现代码5. 循环队列 一、栈 1. 栈的概念 栈是一种特殊的线性表&#xff0c;只允许在固定的一端进行插入和删除操作&#xff0c;该端被称为栈…

自动化测试工具Ranorex Studio(二十五)-库的拆分

默认地&#xff0c;每一个Ranorex Studio项目包含一个对象库文件&#xff0c;这个文件自动用在每一个新创建的录制中。你可以在一个单独的库文件中管理一个测试套件项目中所有的UI元素&#xff0c;但是在一个自动化测试项目中多个对象库的存在还是有一些原因的&#xff1a; .测…

Centos下安装Maven(无坑版)

Linux 安装 Maven Maven 压缩包下载与解压 华为云下载源&#xff0c;自行选择版本 下面的示例使用的是 3.8.1 版本 wget https://repo.huaweicloud.com/apache/maven/maven-3/3.8.1/binaries/apache-maven-3.8.1-bin.tar.gz解压 tar -zxvf apache-maven-3.8.1-bin.tar.gz移…

99、Python并发编程:多线程的问题、临界资源以及同步机制

引言 多线程技术的引入&#xff0c;可以帮助我们实现并发编程&#xff0c;一方面可以充分利用CPU计算资源&#xff0c;另一方面&#xff0c;可以在用户体验上带来极大的改善。但是&#xff0c;多线程技术也存在一些问题。本文就来简单聊一下多线程引入导致的问题&#xff0c;以…

jmeter常用配置元件介绍总结之取样器

系列文章目录 1.windows、linux安装jmeter及设置中文显示 2.jmeter常用配置元件介绍总结之安装插件 3.jmeter常用配置元件介绍总结之取样器 jmeter常用配置元件介绍总结之取样器 2.取样器2.1.HTTP请求2.2.Debug Sampler2.3.JSR223 Sampler2.4.JDBC Connection Configuration和J…

Python练习11

Python日常练习 题目&#xff1a; 编写一个石头剪刀布游戏&#xff0c;该程序要求完成如下功能&#xff1a; (1) 显示游戏规则&#xff0c;提醒用户输入一个1-3的整数或者直接回车。 用户输入回车时游戏结束。 用户输入不合法&#xff08;包括输入的…

什么是欧拉角和四元数

涉及机器人调度工作的一些基本概念整理理解 目录 什么是欧拉角和四元数 &#xff1f;相关工具网站相关工具代码 什么是欧拉角和四元数 &#xff1f; 这里画了一张图&#xff0c;简明方便理解&#xff1a; 欧拉角 (Euler Angles) 是一种描述物体在三维空间旋转姿态的方法&…

关于几种卷积

1*1卷积 分组卷积&深度可分离卷积 空洞卷积、膨胀卷积 转置卷积 https://zhuanlan.zhihu.com/p/80041030 https://yinguobing.com/separable-convolution/#fn2 11的卷积可以理解为对通道进行加权&#xff0c;对于一个通道来说&#xff0c;每个像素点加权是一样的&am…

std::copy

std::copy 是 C 标准库中的一个算法&#xff0c;用于将一个序列中的元素复制到另一个位置。这个算法定义在 <algorithm> 头文件中。 --- 函数原型 std::copy 有几个不同的重载版本&#xff0c;但以下是最常用的两个&#xff1a; template <class InputIterator, c…

PyQt5实战——翻译的实现,第一次爬取微软翻译经验总结(八)

个人博客&#xff1a;苏三有春的博客 系类往期文章&#xff1a; PyQt5实战——多脚本集合包&#xff0c;前言与环境配置&#xff08;一&#xff09; PyQt5实战——多脚本集合包&#xff0c;UI以及工程布局&#xff08;二&#xff09; PyQt5实战——多脚本集合包&#xff0c;程序…