用C++跟你聊聊“原型模式” (复制/拷贝构造函数)

举报
看,未来 发表于 2020/12/29 23:13:40 2020/12/29
【摘要】 从简历投递的故事说起 本来今天不打算用别人的故事了,但是吧,技术这东西,枯燥无味,如果我们连学个东西干嘛用都不知道,那学来干嘛?所以我觉得,这个入门应用场景是很重要的。 今天我去面试了,我需要在简历上填写我的项目经验,格式都是一水的:”XXXX - XX - XX,做过XX项目,任XX职务,收获XXXX“··· 很显然,这可以用一个项目经验类来实现。 但是这一...

在这里插入图片描述

从简历投递的故事说起

本来今天不打算用别人的故事了,但是吧,技术这东西,枯燥无味,如果我们连学个东西干嘛用都不知道,那学来干嘛?所以我觉得,这个入门应用场景是很重要的。

今天我去面试了,我需要在简历上填写我的项目经验,格式都是一水的:”XXXX - XX - XX,做过XX项目,任XX职务,收获XXXX“···
很显然,这可以用一个项目经验类来实现。

但是这一水的项目经验下来,每个经验都要初始化一个实例,成何体统?
好在我项目没过几个,还是可以赏心悦目的。

这时,就可以考虑让一个实例,有多个分身,每个分身再通过类方法修改其成员属性,岂不美哉?那要怎么分身?分身乏术啊,如果不熟悉类的复制构造函数的话。

复制构造函数

知道构造函数的人一般都知道,构造函数分为”深构造“和”浅构造“。如果不知道的话,也不用去别的地方找了,一般来说结果不会很满意,因为我找过了。

浅复制

看这样一个栗子:

class A{};
A *a = new A();
A *b = a;

  
 
  • 1
  • 2
  • 3

像这样把一个对象直接传给另一个对象,一般情况下就是浅复制,是系统默认提供的一种构造方式。但是这种构造方式有什么潜在风险呢?因为是系统支配的,所以它管不到堆区,所以,如果A当中有处于堆区的属性或方法,浅复制是会自动跳过,并且会将它们与原有属性或方法绑定在同一个地址上。

怎么说呢?看栗子:

class A{
	char *a_a;
	char* changea_a();
};
A *a = new A();
A *b = a;

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

首先,初始化a的时候,对a_a进行了空间的分配(函数我就不写了),而后,将a浅复制给b,此时,a的字符串和b的字符串其实指向的是同一块地址。此时,如果通过b调用修改字符串的函数changea_a(),则a对应的字符串也将受到修改。

深复制

何为深复制?想必已经很明确了,就是显式定义的、复制构造函数。
当然,你就算显式定义了,也不一定就是深复制,可能定义出来的还是浅复制。

来看完整栗子:

#include<iostream>
#include<string>

using namespace std;

//工作经历类
class WorkExp {
private:
	string WorkData;
	string Company;
public:
	WorkExp(){};
	string getData() { return WorkData; }
	void setData(string Data) { WorkData = Data; } string getCom() { return Company; }
	void setCom(string Com) { Company = Com; }

	WorkExp(WorkExp& wep) { WorkData = wep.WorkData;
		Company = wep.Company;
	}
};

//简历类
class Resume {
private:
	string name;
	string sex;
	string age;

	WorkExp *work;

public:
	Resume(string name){
		this->name = name;
		work = new WorkExp();
	}

	//Resume(WorkExp *work) { this->work = work; }
	Resume(Resume& res) {
		name = res.name;
		age = res.age;
		sex = res.sex;
		work = new WorkExp(*res.work);	//这是关键点
		//work = res.work;//写成这样就是浅复制
	}
	//设置个人信息
	void SetPersonalInfo(string sex, string age) {
		this->sex = sex;
		this->age = age;
	}

	void SetWorkExp(string workData, string Company) {
		work->setData(workData);
		work->setCom(Company);
	}

	void show()
	{
		cout << "姓名:" << this->name << endl << "性别:"<<this->sex<<endl << "年龄:"<<this->age<< endl;
		cout << "工作经历:" << work->getData() << "	" << "工作公司:" << work->getCom() << endl;
	}
};

int main()
{
	Resume* a = new Resume("啊钒");
	a->SetPersonalInfo("man","22");
	a->SetWorkExp("2017 - 2021", "XX大学");

	Resume b = *a;
	b.SetPersonalInfo("girl", "26");
	b.SetWorkExp("2021 - 2023", "AA公司");

	a->show();
	b.show();

	return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80

原型模式

讲完深浅复制,原型模式其实就很简单了。

在这里插入图片描述

文章来源: lion-wu.blog.csdn.net,作者:看,未来,版权归原作者所有,如需转载,请联系作者。

原文链接:lion-wu.blog.csdn.net/article/details/106120316

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。