当前位置: 首页 > news >正文

c++设计模式二:原型模式

        使用场景:当需要构建多个相同的类对象时,而且该类对象结构较为复杂,如果每个都重新组织构建会很麻烦。

        其实,就是写一个拷贝构造函数,或者写一个拷贝每个成员变量的clone()方法。

        举例说明:比如一个相亲网站需要定义一个“男人”类,可想而知描述清楚一个男人肯定需要很多属性吧,比如姓名、身高、体重、职业、财产大致情况、联系电话、微信号、QQ号等。如果一个男人同时有多个相亲对象时,每次都重新构建填写属性显然太麻烦,所以类中需要定义一个拷贝的方法。

先写一个简单的类:

#pragma once
#include <QString>
class singleMan
{
public:singleMan(QString name,double height,double weight,QString career,QString phoneNum);~singleMan();QString m_name;//姓名double m_height;//身高double m_weight;//体重QString m_career;//职业QString m_phoneNum;//电话};
#include "singleMan.h"
singleMan::singleMan(QString name, double height, double weight, QString career, QString phoneNum):m_name(name),m_height(height),m_weight(weight),m_career(career),m_phoneNum(phoneNum)
{
}singleMan::~singleMan()
{
}

直接赋值,打印出的内容也完全一样,还需要写什么拷贝构造吗?

singleMan sman("LaoWang", 178, 153, "programmer", "19969961024");singleMan sman1 = sman;cout << "sman:" << sman.m_name.toStdString() << ";" << sman.m_phoneNum.toStdString() << endl;cout << "sman1:" << sman1.m_name.toStdString() << ";" << sman1.m_phoneNum.toStdString() << endl;

        这里c++会自动创建一个默认的拷贝构造函数,将成员变量中的值复制一次。但是,当类中有指针类型成员变量时,默认的构造函数仅仅把地址复制一份,两个对象指向的是同一个内存地址,对象销毁时会造成同一个内存被释放两次造成double free,例子如下,添加一个指针类型成员变量-近半年工资流水:

singleman类中添加double* m_monthSalary指针成员变量:

double* m_monthSalary = nullptr;//近半年工资流水

类的析构中释放指针空间:

singleMan::~singleMan()
{if (m_monthSalary!=nullptr){delete m_monthSalary;m_monthSalary = nullptr;}
}
    double salary[6] = { 30000,30000,40000,50000,60000 };sman.m_monthSalary = salary;singleMan sman2 = sman;cout << "sman:" << sman.m_monthSalary[0] << sman.m_monthSalary[1] <<                     sman.m_monthSalary[2] << sman.m_monthSalary[3] << endl;cout << "sman2:" << sman2.m_monthSalary[0] << sman2.m_monthSalary[1] << sman2.m_monthSalary[2] << sman2.m_monthSalary[3] << endl;

调用打印没问题,但是程序结束后会报错:

         所以,这里需要自己写一个拷贝构造函数,实现中需要重新分配新的内存地址(即所谓的深拷贝):

//拷贝构造singleMan(const singleMan& man);//这里要用引用,引用做参数时可减少一次对象拷贝,同时避免了循环拷贝构造问题;
singleMan::singleMan(const singleMan& man)
{m_career = man.m_career;m_height = man.m_height;m_name = man.m_name;m_phoneNum = man.m_phoneNum;m_weight = man.m_weight;m_monthSalary = new double[6];memcpy(m_monthSalary, man.m_monthSalary, 6 * sizeof(double*));
}
    double* salary = new double[6];salary[0] = 30000;salary[1] = 30000;salary[2] = 40000;salary[3] = 50000;salary[4] = 60000;salary[5] = 65000;sman.m_monthSalary = salary;singleMan sman2 = sman;cout << "sman  salary: " << sman.m_monthSalary << endl;cout << "sman2 salary: " << sman2.m_monthSalary << endl;cout << "sman: " << sman.m_monthSalary[0]<<"," << sman.m_monthSalary[1] << "," << sman.m_monthSalary[2] << "," << sman.m_monthSalary[3] << endl;cout << "sman2:" << sman2.m_monthSalary[0] << "," << sman2.m_monthSalary[1] << "," << sman2.m_monthSalary[2] << "," << sman2.m_monthSalary[3] << endl;

        此时,上述问题貌似已经解决了,但是在实际使用过程中会有这种用法:将一个类对象赋值给另一个已经构造好的对象:

    singleMan sman3("LaoLi", 183, 160, "programmer", "19969960512");sman3 = sman;cout << "sman: " << sman.m_name.toStdString() << ";" << sman.m_phoneNum.toStdString() << endl;cout << "sman3:" << sman3.m_name.toStdString() << ";" << sman3.m_phoneNum.toStdString() << endl;cout << "sman  salary: " << sman.m_monthSalary << endl;cout << "sman3 salary: " << sman3.m_monthSalary << endl;cout << "sman: " << sman.m_monthSalary[0] << "," << sman.m_monthSalary[1] << "," << sman.m_monthSalary[2] << "," << sman.m_monthSalary[3] << endl;cout << "sman3:" << sman3.m_monthSalary[0] << "," << sman3.m_monthSalary[1] << "," << sman3.m_monthSalary[2] << "," << sman3.m_monthSalary[3] << endl; 

        这时,就不进入拷贝构造函数了,而是进入了默认的赋值操作符函数中,会有同样的问题,这时需要写一个赋值操作符重载函数:

    //赋值运算符重载(用新的对象的值全部替换原有项)singleMan& operator=(const singleMan& man);
singleMan& singleMan::operator=(const singleMan& man)
{if (m_monthSalary != nullptr){delete m_monthSalary;m_monthSalary = nullptr;}m_career = man.m_career;m_height = man.m_height;m_name = man.m_name;m_phoneNum = man.m_phoneNum;m_weight = man.m_weight;m_monthSalary = new double[6];memcpy(m_monthSalary, man.m_monthSalary, 6 * sizeof(double*));return *this;
}

再次调用问题得到解决:

最后,由于拷贝构造函数中代码和赋值运算符代码几乎一致,可以在拷贝构造函数中直接调研赋值运算符重载函数:

singleMan::singleMan(const singleMan& man)
{/*m_career = man.m_career;m_height = man.m_height;m_name = man.m_name;m_phoneNum = man.m_phoneNum;m_weight = man.m_weight;m_monthSalary = new double[6];memcpy(m_monthSalary, man.m_monthSalary, 6 * sizeof(double*));*/*this = man;
}

        如有问题,欢迎指正! 

参考文献:

【精选】C++创建型模式-原型模式_c++ 原型模式-CSDN博客

4. 原型模式(Prototype) (yuque.com)

相关文章:

c++设计模式二:原型模式

使用场景&#xff1a;当需要构建多个相同的类对象时&#xff0c;而且该类对象结构较为复杂&#xff0c;如果每个都重新组织构建会很麻烦。 其实&#xff0c;就是写一个拷贝构造函数&#xff0c;或者写一个拷贝每个成员变量的clone()方法。 举例说明&#xff1a;比如一个相亲网站…...

【Qt控件之QMessageBox】详解

Qt控件之QMessageBox 描述基于属性的API富文本和文本格式属性严重程度以及图标和Pixmap属性静态函数API 高级用法默认按钮和退出按钮示例使用场景 描述 QMessageBox类提供了一个模态对话框&#xff0c;用于通知用户或向用户提问并接收答案。 消息框显示一个主要文本以提醒用户…...

SSH安全登录远程主机

SSH服务器简介 SSH即Security SHell的意思&#xff0c;它可以将连线的封包进行加密技术&#xff0c;之后进行传输&#xff0c;因此相当的安全。 SSH是一种协议标准&#xff0c;其目的是实现安全远程登录以及其它安全网络服务。 SSH协定&#xff0c;在预设的状态下&#xff0c;…...

揭秘!产品经理提升效率的秘密武器:10款AI生成PPT工具

AI的爆炸式增长表现令人惊艳&#xff0c;现有的各类AI工具正在重塑各行各业&#xff0c;不同程度地提高人们的工作效率&#xff0c;并有望创造新的职业机会。但是&#xff0c;面对市面上数量众多的AI工具&#xff0c;且每周都会蹦出新的产品&#xff0c;即便是以好奇心富称的产…...

Oracle修改带数据的字段类型

insert into TNW_FUND_SELORG(TFDINFOID,TSOINFOID) select TFD_INFO_ID,TSO_INFO_ID from TFD_SEL_FUNDLINK_TO_OLDFUNDWEB_DB /*修改原字段名*/ ALTER TABLE 表名 RENAME COLUMN 字段名 TO 字段名1; /*添加一个和原字段同名的字段*/ ALTER TABLE 表名 ADD 字段名 VARCHAR…...

WebService接口方式和Restful接口这两者有什么区别和相同点

WebService和RESTful接口都是用于在网络上进行通信和数据交换的技术&#xff0c;但它们在设计和使用上有一些重要的区别和相似之处。 相同点&#xff1a; 基于HTTP协议&#xff1a;无论是WebService还是RESTful接口&#xff0c;它们都是通过HTTP协议进行通信的。 支持多种数据…...

jenkins自动化操作步骤(gitblit)

1、登陆地址&#xff1a; http://xxxxxxxxx.org:xxxx/ admin/xxxx 2、创建任务 选择构建一个maven项目 3、配置 最多只保留一天一个任务 选择git仓库和账号密码 选择代码对应分支 build项&#xff1a; 1&#xff09;使用父项目的pom文件&#xff1a;k56-boot/pom.xml 2&…...

centos中mongodb设置服务自启动并 允许远程IP访问

安装mongodb参考 注意的是配置文件需要把journal设置为true 制作为系统服务 创建MongoDB服务文件。运行以下命令创建服务文件/etc/systemd/system/mongod.service&#xff1a; vi /etc/systemd/system/mongod.service [Unit] DescriptionMongoDB Database Server Documenta…...

实时定位和配送追踪:开发万岳同城外卖APP的关键技术特性

随着生活节奏的不断加快&#xff0c;外卖服务已经成为许多人日常生活中不可或缺的一部分。无论是工作日的午餐&#xff0c;还是周末的家庭聚会&#xff0c;外卖APP已经成为满足各种美食需求的首选方式。然而&#xff0c;同城外卖APP的成功不仅仅取决于美味的食物选择&#xff0…...

数据库强化(3.存储过程)

1.什么是存储过程&#xff1f; 存储过程&#xff08;Stored Procedure&#xff09;是一种在数据库中存储复杂程序&#xff0c;以便外部程序调用的一种数据库对象。MySQL 5.0 版本开始支持存储过程。 它是为了完成特定功能的SQL语句集&#xff0c;经编译创建并保存在数据库中&a…...

雅思小作文笔记

mostly from Simon’s methods and techniques remember the task is describe what you see, not give an opinion. Just write a report.no conclusion, just a summary(the overview) Question type 小作文的题目类型大致如上 Simon所述&#xff0c;在描述数字的时候&…...

Java List Set Map

一、List 1.1 ArrayList 1.2 LinkedList 二、Set 2.1 HashSet 2.2 TreeSet 2.3 LinkedHashSet 三、Map 3.1 HashMap 3.2 TreeMap 3.3 LinkedHashMap 四、对比 类型底层结构重复null值场景备注查询删除新增ListArrayList动态数组可允许快速随机访问元素0(1)0(n)尾部增加0&a…...

【数据结构】数组和字符串(十三):链式字符串的基本操作(串长统计、查找、复制、插入、删除、串拼接)

文章目录 4.3 字符串4.3.1 字符串的定义与存储4.3.2 字符串的基本操作&#xff08;链式存储&#xff09;1. 结构体2. 初始化3. 判空4. 串尾添加5. 打印6. 串长统计7. 查找8. 复制9. 插入10. 删除11. 串拼接12. 销毁13. 主函数14. 代码整合 4.3 字符串 字符串(String)是由零个或…...

Python3 获取当前服务器公网 IP 地址

有同学问我如何使用 Python 获取服务器公网的 IP 地址呢&#xff1f;我测试几个发现&#xff0c;方法有很多&#xff0c;好用的就发现一种&#xff0c;即直接使用 Python 自带的 socket 包。 代码示例&#xff1a; # 获取主机 IP dgram socket.socket(socket.AF_INET, socke…...

EAS查前5分钟到现在的组织变动数据

select * from T_ORG_Admin where ( (FCREATETIME between ( sysdate-(1/24/60)*8) and sysdate ) or (FLASTUPDATETIME between ( sysdate-(1/24/60)*8) and sysdate ) ) -- FLASTUPDATETIME < sysdate-(1/24/60)*10 --FNUMBER 110112...

uni-app——如何阻止事件冒泡

引言 在开发移动应用程序时&#xff0c;我们经常需要处理用户交互事件。然而&#xff0c;有时候这些事件会冒泡&#xff0c;导致意外的行为和不良用户体验。在本文中&#xff0c;我们将探讨如何使用UniApp框架来阻止事件冒泡&#xff0c;并提供一些示例代码来帮助您理解如何实…...

[MySQL]索引

目录 概念解释 作用/优点 缺点 适用场景 索引的创建,删除与查看 系统对索引的自动创建 索引建立的时机 索引存储的数据结构 选择B树的原因 B树的原理 查询流程 优点 B树 与B树的区别 优点 概念解释 索引就像是一本字典的目录,我们可以根据目录快速定位到我们想…...

什么是AUTOSAR ComStack,AUTOSAR架构中,CAN通信堆栈CAN Communication Stack介绍

AUTOSAR&#xff08;Automotive Open System Architecture&#xff09;ComStack指的是AUTOSAR架构中的通信堆栈。在AUTOSAR体系结构中&#xff0c;ComStack是指用于不同软件组件&#xff08;如应用软件、基础软件等&#xff09;之间进行通信的一组协议和服务。 在AUTOSAR架构中…...

黄金期货与黄金现货的区别

黄金期货与黄金现货是有区别的&#xff0c;比如在交易机制方面&#xff0c;黄金期货有具体的交割日&#xff0c;合约到期就必须交割&#xff0c;否则会被强行平仓或以实物进行交割&#xff0c;而在保证金不足时也会被强行平仓&#xff1b;而现货黄金就没有交割限制&#xff0c;…...

【数据结构】数组和字符串(五):特殊矩阵的压缩存储:稀疏矩阵——压缩稀疏行(CSR)

文章目录 4.2.1 矩阵的数组表示4.2.2 特殊矩阵的压缩存储a. 对角矩阵的压缩存储b~c. 三角、对称矩阵的压缩存储d. 稀疏矩阵的压缩存储——三元组表e. 压缩稀疏行&#xff08;Compressed Sparse Row&#xff0c;CSR&#xff09;矩阵结构体创建CSR矩阵元素设置初始化打印矩阵销毁…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...