copy构造函数和copy assignment操作符,我们称他们为copying函数。这些“编译器生成版”的行为:将被烤对象的所有成员变量
都做一份拷贝。
声明自己的copying函数,
void logCall(const std::string funcName);
class Customer
{
public:
Customer(const Customer& rhs);
Customer& operator=(const Customer& rhs);
protected:
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:
Customer(const Customer& rhs);
Customer& operator=(const Customer& rhs);
protected:
private:
std::string name;
Date lastTransaction;
};
这时既有的copying函数就是局部拷贝:他们的确复制了name但没有复制新添加的lastTransaction。如果你为class添加一个成员变量,你必须同时修改copying函数。(你也需要修改所有的构造函数以及任何非标准形式的operator=)。
一旦发生继承,可能会造成此一主题最暗中肆虐的一个潜藏危机。试考虑:
class PriorityCustomer : public Customer
{
public:
PriorityCustomer(const PriorityCustomer& rhs);
PriorityCustomer& operator=(const PriorityCustomer& rhs);
protected:
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构造函数,因此PriorityCustomer对象的Customer成分会被不带实参的default构造函数初始化。default构造函数将对name和lastTransaction执行缺省的初始化动作。
base class 的成分往往是private, 所以你无法直接访问他们,你应该让derived class的copying函数调用相应的base class函数:
PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs)
:Customer(rhs), //调用base class的copy构造函数
priority(rhs.priority)
{
logCall("PriorityCustomer copy constructor");
}
PriorityCustomer& PriorityCustomer::operator=(const PriorityCustomer& rhs)
{
logCall("PriorityCustomer copy assignment operator");
Customer::operator =(rhs); //对base class成分进行赋值动作
priority = rhs.priority;
return *this;
}
当你编写一个copying函数,请确保1.复制所有的local成员变量,2.调用所有的base class内的适当的copying函数。
当这两个copying函数有近似相同的实现本体,令一个copying函数调用另一个copying函数无法让你达到你想要的目标。
令copy assignment调用copy构造函数是不合理的,因为这像试图构造一个已经存在的对象。
反方向令copy构造函数调用copy assignment操作符,同样无意义,相当于在一个未构造好的对象赋值。
消除重复代码的做法是:建立一个新的成员函数给两者调用。这样的函数往往是private而且常被命名为init。
原文链接: https://www.cnblogs.com/lidan/archive/2012/01/13/2322098.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/40127
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!