Fork me on GitHub Fork me on GitHub

EC读书笔记系列之7:条款12 复制对象时勿忘其每一个成分

记住:

★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之间的代码重复。

posted @ 2015-11-04 14:31  墨城烟雨  阅读(204)  评论(0编辑  收藏  举报