复制对象时勿忘其每一个成分

前言:看了好久Effective,但是感觉好多都是看了就忘,现在再看一边,顺便把一些易忘的记录下来,争取每天一记。

概念:Copying函数,包括copy constructor;copy assignment operator,对于默认的编译器生成版,会将被拷贝的对象的所有成员变量都做一份拷贝。

如果你自己声明一个copying函数,编译器就会以一种奇怪的方式回应:当你的实现代码几乎必然出错时却不告诉你.(不知道是作者原话还是译者,感觉挺有意思的)

该条款有两个需要注意的地方:1复制所有local成员变量2调用所有base classes内的copying函数。

第一个地方还好,比较容易理解,下面主要讲讲第二个->

 

 


  1. void logCall(const std::string& funcName);          // make a log entry   
  2. class Customer {   
  3. public:   
  4.   …   
  5.   Customer(const Customer& rhs);   
  6.   Customer& operator=(const Customer& rhs);   
  7.   …   
  8. private:   
  9.   std::string name;   
  10. };   
  11.   
  12. Customer::Customer(const Customer& rhs)   
  13. : name(rhs.name)                                 // copy rhs’s data   
  14. {   
  15.   logCall(“Customer copy constructor”);   
  16. }   
  17.   
  18. Customer& Customer::operator=(const Customer& rhs)   
  19. {   
  20.   logCall(“Customer copy assignment operator”);   
  21.   name = rhs.name;                                  
  22.   return *this;                                     
  23. }   
  24.   
  25. class Date { … };       // for dates in time   
  26.   
  27. class Customer {   
  28. public:   
  29.   …                     // as before   
  30. private:   
  31.   std::string name;   
  32.   Date lastTransaction;   
  33. };   
  34.   
  35. class PriorityCustomer: public Customer {                  // a derived class   
  36. public:   
  37.    …   
  38.    PriorityCustomer(const PriorityCustomer& rhs);   
  39.    PriorityCustomer& operator=(const PriorityCustomer& rhs);   
  40.    …   
  41. private:   
  42.    int priority;   
  43. };   
  44.   
  45. PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs)   
  46. : priority(rhs.priority)   
  47. {   
  48.   logCall(“PriorityCustomer copy constructor”);   
  49. }   
  50. PriorityCustomer& PriorityCustomer::operator=(const PriorityCustomer& rhs)   
  51. {   
  52.   logCall(“PriorityCustomer copy assignment operator”);   
  53.   priority = rhs.priority;   
  54.   return *this;   
  55. }  

PriorityCustomer类的copying函数好像复制了PriorityCustomer内的每一样东西,它复制了PriorityCustomer声明的成员变量,但是其基类Customer成员变量却没有被复制(其实应该是没有按照相应的参数复制,而是使用了这些变量的default构造函数),这一点是尤其需要注意的,尤其是没有真正写过类似代码时很容易忽视这个问题,正确的写法是下面这样的:

 


  1. PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs)   
  2. :Customer(rhs),                   // invoke base class copy ctor   
  3.  priority(rhs.priority)   
  4. {   
  5.   logCall(“PriorityCustomer copy constructor”);   
  6. }   
  7.   
  8.   
  9. PriorityCustomer& PriorityCustomer::operator=(const PriorityCustomer& rhs)   
  10. {   
  11.   logCall(“PriorityCustomer copy assignment operator”);   
  12.   Customer::operator=(rhs);           // assign base class parts   
  13.   priority = rhs.priority;   
  14.   return *this;   
  15. }  

具体内容见Items12。