用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;
}

原型模式

講完深淺複製,原型模式其實就很簡單了。

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章