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

copy 函数

设计良好之面向对象系统会将对象的内部封装起来,只留两个函数负责对象拷贝(复制),copy构造函数和co培养assignment 操作符。

如果你声明自己的copying函数,意思是告诉编译器你并不喜欢缺省实现中的某些行为。编译器会以一种奇怪的方式回敬:当你的实现代码几乎必然出错却不告诉你

void logCall(const std::string& funcName);
class Customer{
public :
  ...
 Customer(const Customer&rhs);
 Customer& operator=(const Customer &rhs);
 ...
 private:
 std::string name;
};
Customer::Customer(const Customer &rhs):name (rhs.name)
{
  logCall("Customer copy constructor");
}
Customer &Customer::operator=(const Customer&rhs)
{
  logCall("Customer copy assignment operator");
  name = rhs.name;
  return *this;
}

如果另一个成员变量加入战局

class Date{...};
class Customer{
public:
   ...       //同前
private:
  std::string name;
  Date lastTransaction;  
}


这时既有的copying函数执行的是局部拷贝:复制了name,没有新添加复制的lastTransaction。编译器不会发生怨言。


如果你为class添加一个变量,你必须同时修改copy函数(还有class内所有构造函数以及任何非标准形式的operator=)

一旦发生继承

 class PriorityCustomer:public Customer{
 public:
  ...
  PriorityCustomer(const PriorityCustomer &rhs);
  PriorityCustomer& operator=(const PriorityCustomer &rhs);
  ...
  private:
  int priority;
 };
 PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs):priority(rhs.priority)
 {
   logCall("PriorityCustomer copy constructor");
 }
  PriorityCustomer&PriorityCustomer::operator=(const PriorityCustomer &rhs)
 {
    logCall("PriorityCustomer copy assignment operator");
    priority = rhs.priority;
   return *this;
 }

PriorityCustomer的copying函数复制了PriorityCustomer内声明的成员变量,但每个PriorityCustomer还内涵它所继承的Customer成员变量复件(副本),而那些成员变量并未复制。PriorityCustomer的copy构造函数并没有指定的实参传给base class构造函数(也就是说它在它的成员初值列中没有提到Customer),因此PriorityCustomer对象Customer成分会被不带实参之Customer构造函数(即default构造函数)初始化。default构造函数将针对name和lastTransaction执行缺省的初始化动作。


任何时候需要“为derived class 撰写copying函数”的重责大任,必须复制其base class 成分。应该用derived class 的copying函数调用相应的base class函数。

 PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs):Customer(rhs),priority(rhs.priority)
 {
   logCall("PriorityCustomer copy constructor");
 }
  PriorityCustomer&PriorityCustomer::operator=(const PriorityCustomer &rhs)
 {
    logCall("PriorityCustomer copy assignment operator");
    Customer::operator=(rhs);
    priority = rhs.priority;
   return *this;
 }
当编写一个copying函数,请确保 (1)复制所有local成员变量 (2)调用所有base class 内的适当的copying函数

如果copy函数和copy assignment操作符有相近的代码,消除重复代码的做法是,建立一个新的成员函数给两者调用。这样的函数往往是private而且常被命名为init.


Copying函数应该确保复制“对象内所有成员变量”及“所有base class”成分。

不要尝试以某个copy函数实现另一个copy函数。应该将共同机能放进第三个函数中,并由两个coping函数共同调用。


你可能感兴趣的:(effect,C++)