Effective C++ 条款12_不止于此

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

设计良好之面向对象系统会将对象的内部封装起来,只留两个函数负责对象拷贝(copy 构造函数和 copy assignment 操作符)
在 C++ 中,如果自己声明 copying 函数,会发生这样一种情况:当你的实现代码几乎必然出错时却不告诉你。
看下面的代码说事:

void logCall(const std::string& funcName);  // 制造一个 log entry
class Customer {
public:
	...
	Customer(const Customer& r);
	Customer& operator=(const Customer& r);
	...
private:
	std::string name;
	};
Customer::Customer(const Customer& r): name(r.name){   // 复制 r 的数据
	logCall("Customer copy constructor");
	}
Customer& Customer::operator=(const Customer& r){
	logCall("Customer copy assignment operator");
	name = r.name;			// 复制 r 的数据
	return *this;
	}

这样做看起来很好,实际也很好,但如果另一个变量的加入就会打破这个美好的局面:

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

这时候上面的 copying 函数执行的就是局部构造:
复制了 name,但是没有复制新添加的 lastTransaction。但大多数的编译器都不会报错。

一但发生继承,将面临这一主题最暗中肆虐的危机:

class vipCustomer: public Customer {  	// 一个 derived class
public: 
	...
	vipCustomer(const vipCustomer& r);
	vipCustomer& operator=(const vipCustomer& r);
private:
	 int vip;
	};

vipCustomer::Customer(const vipCustomer& r): vip(r.vip){   // 复制 r 的数据
	logCall("vipCustomer copy constructor");
	}
vipCustomer& vipCustomer::operator=(const vipCustomer& r){
	logCall("vipCustomer copy assignment operator");
	vip = r.vip;			// 复制 r 的数据
	return *this;
	}

vipCustomer 的 copying 函数只是复制了 vipCustomer 声明的成员变量,但是它还含有从 base class 继承的成员变量附件(副本),但没有被复制。因此 base class 的成员变量保持不变。

在为 derived class 撰写 copying 函数时,都必须小心地也复制其 base class 的成分。那些成分往往是 private 的,所以应该让 derived class 的 copying 函数调用相应的 base class 函数:

vipCustomer::Customer(const vipCustomer& r): 
	Customer(r);	// 调用 base class 的 copy 构造函数
	vip(r.vip){   // 复制 r 的数据
	logCall("vipCustomer copy constructor");
	}
vipCustomer& vipCustomer::operator=(const vipCustomer& r){
	logCall("vipCustomer copy assignment operator");
	Customer::operator(r);   // 对 base class 成分进行赋值操作
	vip = r.vip;			// 复制 r 的数据
	return *this;
	}

上面只是简单介绍,详细内容会在条款22细说。
copy 构造函数和 copy assignment 操作符不能相互调用!

最后记住:

  • Copying 函数应该确保复制 “ 对象内的所有成员变量 ” 及 “ 所有 base class 成分 ”。
  • 不要尝试以某个 copying 函数实现另一个 copying 函数。应该将共同机能放进第三个函数中,并由两个 copying 函数共同调用。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值