從簡歷投遞的故事說起
本來今天不打算用別人的故事了,但是吧,技術這東西,枯燥無味,如果我們連學個東西幹嘛用都不知道,那學來幹嘛?所以我覺得,這個入門應用場景是很重要的。
今天我去面試了,我需要在簡歷上填寫我的項目經驗,格式都是一水的:”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;
}
原型模式
講完深淺複製,原型模式其實就很簡單了。