C++進階--擁有資源句柄的類(淺拷貝,深拷貝,虛構造函數)
阿新 • • 發佈:2018-12-24
拷貝 保存 ... 代碼 cpp 不同的 容易 淺拷貝 聲明
// Person通過指針擁有string class Person { public: Person(string name) { pName_ = new string(name); } ~Person() { delete pName_; } void printName() { cout << *pName_; } private: string* pName_; }; int main() { vector<Person> persons; persons.push_back(Person("George")); persons.front().printName(); //這裏會崩 cout << "Goodbye" << endl; } //persons.push_back(Person("George")); 事實上該行代碼可以分解成以下步驟 // 1. "George" 被構造 // 2. "George"的一個副本保存到(淺拷貝) // 3. "George"被銷毀 // Solution 1: 定義拷貝構造和拷貝賦值實現深拷貝 Person(const Person& rhs) { pName_ = new string(*(rhs.pName())); } Person& operator=(const Person& rhs); string* pName() const { return pName_; } // Solution 2: 禁用拷貝構造和拷貝賦值 // 對C++ 11,使用=delete // for C++ 03, 聲明但不定義 Person(const Person& rhs); Person& operator=(const Person& rhs); // 如果禁用之後仍然需要拷貝,使用clone() // 顯式的拷貝 Person* clone() { return (new Person(*(pName_))); } // 更推薦方法2: // 1. 因為拷貝構造和拷貝賦值經常並不需要 // 2. 使拷貝顯式,隱式拷貝容易出現bug // 3. clone可以利用多態實現虛構造函數,自動根據指針所指對象的類型拷貝基類或者派生類對象 class Dog { public: virtual Dog* clone() { return (new Dog(*this)); } //co-variant return type 允許覆寫函數具有不同的返回類型,只要返回類型由基類的返回類型派生得到 }; class Yellowdog : public Dog { virtual Yellowdog* clone() { return (new Yellowdog(*this)); } }; void foo(Dog* d) { // d 是Yellowdog //Dog* c = new Dog(*d); // c 是Dog,不是我們想要的 Dog* c = d->clone(); // c是Yellowdog //... // } int main() { Yellowdog d; foo(&d); } // C++ 11 的方法: // shared_ptr<string> pName_; // 大多數情況下用unique_ptr也可以, 但是跟STL container一起使用時必須使用shared_ptr, // 因為STL容易要求元素時可拷貝的
C++進階--擁有資源句柄的類(淺拷貝,深拷貝,虛構造函數)