记住:
★copying函数应确保复制“对象内的所有成员变量”及“所有base class成分”
★不要尝试以某个copying函数实现另一个copying函数。应该将共同机能放进第三个函数中,并由两个copying函数共同调用
---------------------------------------------------------------
copying函数包括:copy constructor和copy assignment operator
引出问题的例子:
1 class Customer { 2 3 public: 4 ... 5 Customer( const Customer &rhs ); 6 Customer& operator=( const Customer &rhs ); 7 ... 8 private: 9 std::string name; 10 Date lastTransaction; 11 };
当发生继承时,有一个潜藏危机:
1 class PriorityCustomer : public Customer { 2 3 public: 4 ... 5 PriorityCustomer( const PriorityCustomer &rhs ); 6 PriorityCustomer& operator=( const PriorityCustomer &rhs ); 7 ... 8 private: 9 int priority; //派生类独有的成员 10 }; 11 12 PriorityCustomer::PriorityCustomer( const PriorityCustomer &rhs ):priority( rhs.priority ) { 13 14 logCall( "PriorityCustomer copy constructor" ); 15 } 16 17 PriorityCustomer& PriorityCustomer::operator=( const PriorityCustomer &rhs ) { 18 19 logCall( "PriorityCustomer copy assignment operator" ); 20 priority = rhs.priority; 21 return *this; 22 }
PriorityCustomer的copying函数看起来好像赋值了PriorityCustomer内的每个东西,但实际每个PriorityCustomer还内含有它所继承的基类:Customer成员变量复件,而那些成员变量却未被复制,这种情况特别容易忽视!!!
改进如下:
1 PriorityCustomer::PriorityCustomer( const PriorityCustomer &rhs ) 2 :Customer( rhs ), //不要忘了调用base class的copy constructor!!! 3 priority( rhs.priority ) { 4 5 logCall( "PriorityCustomer copy constructor" ); 6 } 7 8 PriorityCustomer& PriorityCustomer::operator=( const PriorityCustomer &rhs ) { 9 10 logCall( "PriorityCustomer copy assignment operator" ); 11 Customer::operator=( rhs ); //不要忘了对base class成分进行赋值操作 12 priority = rhs.priority; 13 return *this; 14 }
本条款所说的“复制每一个成分”,意指当你编写一个copying函数,应确保:
(1)复制所有local成员变量;
(2)调用所有base classes内的适当的copying函数
若发现copy constructor和copy assignment operator有相近的代码,为了消除重复代码,应建立一个新的成员函数给两者调用(此函数往往是private且常被命名为init)。此策略可以安全消除copy constructor和copy assignment operator之间的代码重复。