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

在这里插入图片描述

从简历投递的故事说起

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

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

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

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

复制构造函数

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

浅复制

看这样一个栗子:

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

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

怎么说呢?看栗子:

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

首先,初始化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;
}

原型模式

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

在这里插入图片描述

原创文章 158 获赞 995 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_43762191/article/details/106120316