这是《Effective C++》中条款12的读书笔记。
copy构造函数和copy assignment操作符,称为copying函数。
通常情况下编译器有默认的构造函数和赋值操作符,这两个函数都可以将被拷对象的所有成员变量做一份拷贝。但是当程序员声明自己的copying函数的时候,编译器不再做默认的拷贝操作。
例如下面一个Customer类:
class Customer
{
public:
...
Customer(const Customer& rhs);
Customer& operator=(const Customer& rhs);
...
private:
std::string name;
};
Customer::Customer(const Customer& rhs) : name(rhs.name)
{
printf("Customer copy constructor");
}
Customer::Customer& operator=(const Customer& rhs)
{
printf("Customer copy assignment operator");
name = rhs.name;
return* this
}
这里的Customer定义了自己的构造函数和赋值操作符。当在类中添加一个私有变量,问题逐渐浮现:
class Customer
{
public:
...
Customer(const Customer& rhs);
Customer& operator=(const Customer& rhs);
...
private:
std::string name;
Data lastTransaction;
};
此时如果没有的自定义构造函数中复制lastTransaction,编译器不会做出任何提示。很明显的是,你为class添加一个成员变量,就必须同时修改copying函数。
当有继承发生的时候,隐藏了一个更大的危机。例如:
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)
{
printf("PriorityCustomer copy constructor");
}
PriorityCustomer::PriorityCustomer& operator=(const PriorityCustomer& rhs)
{
printf("PriorityCustomer copy assignment operator");
priority = rhs.priority;
return *this;
}
PriorityCustomer的copying函数看起来好像复制了类内的每一样东西,但是PriorityCustomer还内涵它所继承的Customer成员变量,而那些成员变量却未被复制。当自己定义copying函数时,也必须复制其基类的成分,而这些成分往往是private,所以无法直接访问基类的private,应该让派生类的copying函数调用相应的基类函数。如下:
PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs) : Customer(rhs), priority(rhs.priority)
{
printf("PriorityCustomer copy constructor");
}
PriorityCustomer::PriorityCustomer& operator=(const PriorityCustomer& rhs)
{
printf("PriorityCustomer copy assignment operator");
Customer::operator =(rhs);
priority = rhs.priority;
return *this;
}
当你编写一个copying函数时,需要确保:
1.复制所有local成员变量
2.调用所有base class内适当的copying函数