c++编程习惯十一(复制对象时不要忘记其任一成分)

设计良好的面向对象系统会将对象的内部封装起来,只留两个函数负责对象拷贝(复制),就是copy构造函数和赋值操作符,我们称之为copying函数。前面我说了,编译器会在必要时候为我们的类生成copying函数,并说明这些“编译器生成版”的行为:将被拷贝对象的所有成员都拷贝一份。

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

 

考虑一个类用来表现顾客,其中手工写出copying函数,使得外界对它们的调用会被志记下来:

void logCall(const std :: string& funcName); //制造一个log entry
class Customer
{
public:
	...
	Customer(cosnt Customer& rhs);
	Customer& operator = (const Customer& rhs);
	...
	~Customer();
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 constructor");
	name = rhs.name;

	return *this;
}

 

这里每一件事看起来都很顺利,实际也如此,直到令一个成员变量加入:

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

这时候已经有的copying函数执行的是局部拷贝:它们的确复制了顾客的name,但没有复制新添加的lastTransaction。大多数编译器对此不会有报错,结论就是:你既然自己写了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)
{
	logCall("PriorityCustomer copy constructor");
}

PriorityCustomer& PriorityCustomer::operator = (const PriorityCustomer& rhs)
{
	logCall("PriorityCustomer copy assignment operator");
	priority = rhs.priority;
	return *this;
}

看起来该类的copying函数好想复制了每一样东西,但再看一眼,我们忘了基类中的name和lastTransaction,所以要记得在copying函数上补上,我这里就不过多赘述了。

 

当你编写一个copying函数,请确保1、复制所有local成员变量,2、调用基类内适当的copying函数。

 

总结:

1、copying函数应该确保复制“对象内的所有成员变量“及“所有基类成分“;

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

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值