首先要说的是当对一个已经定义了构造函数以及赋值运算符(拷贝)的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 Customer15 {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函数中公共的部分