条款12:复制对象的时候不要忘了其每一个部分
首先要说的是当对一个已经定义了构造函数以及赋值运算符(拷贝)的class增加了成员的时候,一定要记得为这个class重新改写构造函数以及拷贝赋值运算符。
下一个容易遗忘的点在继承中,看下面的代码:
1 class Customer 2 { 3 public: 4 //... 5 Customer(const Customer & rhs):name(rhs){} 6 Customer & operator=(const Customer & rhs) 7 { 8 //... 9 } 10 private: 11 std::string name; 12 } 13 //再考虑继承的情况。 14 class PriorityCustomer:public Customer 15 { 16 public: 17 //... 18 PriorityCustomer(const PriorityCustomer & rhs) 19 :priority(rhs.priority) 20 { 21 //... 22 } 23 PriorityCustomer & operator=(const PriorityCustomer & rhs) 24 { 25 priority = rhs.priority; 26 return *this; 27 } 28 }
看着好像没错,但是基类事实上没有被构造,应该在derived class中显式的调用base class的构造函数。像下面这样:
1 class PriorityCustomer:public Customer 2 { 3 public: 4 //... 5 PriorityCustomer(const PriorityCustomer & rhs) 6 :priority(rhs.priority) 7 Customer(rhs) 8 { 9 //... 10 } 11 PriorityCustomer & operator=(const PriorityCustomer & rhs) 12 { 13 Customer::operator=(rhs);//这个用法要注意,不然会引起循环递归 14 priority = rhs.priority; 15 return *this; 16 } 17 }
PS:如果发现copy constructor和copy assignment operator有着相似的代码,消除重复代码的方法是,建立一个新的private成员函数给二者用,一般名字为init()
小结:应该记住的两点是 1. copying函数应该确保复制对象里面你的所有函数包括进行基类的完整构造 2.如果两个copy函数中有相同的部分,
不要尝试用一个区调用另一个,而应该另外声明一个函数处理两个coping函数中公共的部分