Effective C++(12) 复制对象时要复制每一个成员
2013-12-31 09:29
232 查看
问题聚焦:
负责拷贝的两个操作:拷贝构造函数和重载赋值操作符。
一句话总结,确保被拷贝对象的所有成员变量都做一份拷贝。
Demo
上述代码的问题很明显,就是没有拷贝lastTransaction成员变量,更为严重的是,编译器并不会提醒你这个错误。
结论就是,如果为class添加一个成员变量,必须同时修改copying函数(包括拷贝构造函数和重载赋值操作符)
如果发生了继承,会带来什么样的危险呢?
问题:
PriorityCustomer的拷贝函数们拷贝了它声明的成员变量,却忽略了它所继承的Customer成员变量的拷贝,也没有指定实参传递给Customer的构造函数,因此,PriorityCustomer对象的Customer成分会被不带实参的Customer默认构造函数初始化。
改进:为子类编写拷贝函数时,必须要复制其基类部分。
结论
确保赋值所有local成员变量
调用所有base classes内的适当的拷贝函数
需要注意的一点是:
虽然重载赋值操作符和拷贝函数的代码长得很像,但是很难复用它们,因为重载赋值操作符时调用拷贝构造函数就像在构造一个已经存在的对象;
同样地,令拷贝构造函数调用重载赋值操作符一样没有意义。
所以,复用这两个代码的方式就是写一个新的成员函数给两者调用。
小结:
拷贝构造函数和重载赋值操作符应该确保复制“对象内的所有成员变量”及“所有base class成分”;
不要尝试拷贝构造函数调用重载赋值操作符或是反过来。
参考资料:
《Effective C++ 3rd》
负责拷贝的两个操作:拷贝构造函数和重载赋值操作符。
一句话总结,确保被拷贝对象的所有成员变量都做一份拷贝。
Demo
void logCall(const std::string& funcName); // log函数 class Date{ ... }; class Customer { public: .... Customer(const Customer& rhs); Customer& operator=(const Customer& rhs); private: std::string name; Date lastTransaction; }; Customer::Customer(const Customer& rhs) : name(rhs.name) // 忽略了lastTransaction成员变量 { logCall("Customer copy constructor"); } Customer& Customer::operato=(const Customer& rhs) { logCall("Customer copy assignment operator"); name = rhs.name; // 忽略了lastTransaction成员变量 return *this; }
上述代码的问题很明显,就是没有拷贝lastTransaction成员变量,更为严重的是,编译器并不会提醒你这个错误。
结论就是,如果为class添加一个成员变量,必须同时修改copying函数(包括拷贝构造函数和重载赋值操作符)
如果发生了继承,会带来什么样的危险呢?
class PriorityCustomer: public Custoer { public: ... PriorityCustomer(const PriorityCustoer& rhs); PriorityCustomer& operato=(const PriorityCustomer& rhs); ... private: int priority; }; PriorityCustomer& PriorityCustomer::PriorityCustomer (const PriorityCustomer& rhs) : priority(rhs.priority) { logCall("PriorityCustoer copy constructor"); } PriorityCustomer& PriorityCustomer::operator=(const PriorityCustomer& rhs) { logCall("PriorityCustomer copy assignment operator"); priority = rhs.priority; return *this; }
问题:
PriorityCustomer的拷贝函数们拷贝了它声明的成员变量,却忽略了它所继承的Customer成员变量的拷贝,也没有指定实参传递给Customer的构造函数,因此,PriorityCustomer对象的Customer成分会被不带实参的Customer默认构造函数初始化。
改进:为子类编写拷贝函数时,必须要复制其基类部分。
PriorityCustomer& PriorityCustomer::PriorityCustomer (const PriorityCustomer& rhs) : Customer(rsh), priority(rhs.priority) { logCall("PriorityCustoer copy constructor"); } PriorityCustomer& PriorityCustomer::operator=(const PriorityCustomer& rhs) { logCall("PriorityCustomer copy assignment operator"); Customer::operator=(rhs); priority = rhs.priority; return *this; }
结论
确保赋值所有local成员变量
调用所有base classes内的适当的拷贝函数
需要注意的一点是:
虽然重载赋值操作符和拷贝函数的代码长得很像,但是很难复用它们,因为重载赋值操作符时调用拷贝构造函数就像在构造一个已经存在的对象;
同样地,令拷贝构造函数调用重载赋值操作符一样没有意义。
所以,复用这两个代码的方式就是写一个新的成员函数给两者调用。
小结:
拷贝构造函数和重载赋值操作符应该确保复制“对象内的所有成员变量”及“所有base class成分”;
不要尝试拷贝构造函数调用重载赋值操作符或是反过来。
参考资料:
《Effective C++ 3rd》
相关文章推荐
- 《Effective C++》学习笔记条款12 复制对象时勿忘其每一个成员
- effective c++ 条款12 赋值对象时勿忘其每一个成员
- Effective C++ 条款12:复制对象时勿忘其每一个成分
- Effective C++:条款12:复制对象时勿忘其每一个成分
- effective C++ 12_复制对象时勿忘其每一个成分 读书笔记
- Effective C++ 条款12 复制对象时勿忘其每一个部分
- effective C++ 条款 12:复制对象时勿忘其每一个成分
- Effective C++ -----条款12: 复制对象时勿忘其每一个成分
- Effective C++ 条款12:复制对象时勿忘其每一个成分 学习笔记
- 读书笔记《Effective c++》 条款12 复制对象时勿忘其每一个成分
- effective c++ 条款12 赋值对象时勿忘其每一个成员
- 【effective c++】 条款12:复制对象时勿忘其每一个成分
- Effective C++:规定12:不要忘了复制的对象时,它的每一个组成部分
- Effective C++_笔记_条款12_复制对象时勿忘其每一个成分
- Effective C++ 学记之12 复制对象时勿忘其每一个成分
- Effective C++ 条款11,12 在operator= 中处理“自我赋值” || 复制对象时不要忘记每一个成分
- 复制对象时勿忘其每一个成分(Effective C++_12)
- 《Effective C++》条款12:复制对象是勿忘其每一个成分
- C++之复制对象时勿忘每一个成分(12)---《Effective C++》
- [Effective C++ --012]复制对象时勿忘其每一个成分