?编译器生成的拷贝函数(拷贝构造函数,拷贝赋值运算符),会拷贝对象的所有数据,当你声明自己的拷贝函数时,就是在告诉编译器,默认实现中有你不喜欢的地方。
void logCall(const std::string& funcName); // 创造一条记录
class Date { ... }; // 日期
class Customer {
public:
...
Customer(const Customer& rhs);
Customer& operator=(const Customer& rhs);
...
private:
std::string name;
Date lastTransaction; // 后期添加的成员
};
Customer::Customer(const Customer& rhs)
: name(rhs.name) // 拷贝rhs的数据
{
logCall("Customer copy constructor");
}
Customer& Customer::operator=(const Customer& rhs)
{
logCall("Customer copy assignment operator");
name = rhs.name; // 拷贝rhs的数据
return *this; // 见条款10
}
拷贝时,后期添加的成员被遗忘了。
出现这个问题的最狡猾的方式之一是通过继承。
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;
}
在调用赋值的时候data数据由于没有进行赋值拷贝,所以在子类的赋值中缺失了该数据。
?派生类复制函数必须调用它们对应的基类函数。
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;
}
如果没有调用的话进行赋值的时候就会导致基类部分的数据没有赋值过去。
如果两个拷贝函数有很多重复代码,可以先构造一个,再用另一个调用它吗?不要这样做!!!构造函数会初始化新对象,但赋值运算符只适用于已经初始化的对象。