侧边栏壁纸
博主头像
如此肤浅

但行好事,莫问前程!

  • 累计撰写 52 篇文章
  • 累计创建 6 个标签
  • 累计收到 6 条评论

目 录CONTENT

文章目录

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

如此肤浅
2022-05-17 / 0 评论 / 0 点赞 / 45 阅读 / 1,877 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-05-17,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

1. 拷贝构造(赋值)函数应该确保复制“对象内的所有成员变量”及“所有 base class 成分”。
2. 不要尝试以某个拷贝函数实现另一个拷贝函数。应该将共同机能放进第三个函数中,并由两个拷贝函数共同调用。例如,创建一个 private 的初始化函数而且常被命名为init,可消除拷贝构造和拷贝赋值操作符之间的代码重复。

void logCall(const std::string& funcName); // 记录日志
class Customer {
public:
	...
    Customer(const Custoer& rhs);
    Customer& operator=(const Customer& rhs);
    ...
private:
	std::string name;
};
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;
}
// 一个派生类
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& PriorityCustoer::operator=(const PriorityCustomer& rhs)
{
	logCall("PriorityCustomer copy assignment operator");
    priority = rhs.priority;
    return *this;
}

PriorityCustomer 的 拷贝构造(赋值)函数看起来好像复制了 PriorityCustomer 内的每一个它声明的成员变量,但每个 PriorityCustomer 还内含它所继承的 Customer 成员变量副本,而那些成员变量却未被复制。

PriorityCustomer 的 拷贝构造函数并没有指定实参传给其 base class 构造函数(也就是说它在它的成员初值列中没有提到 customer),因此 PriorityCustomer 对象的 customer 成分会被不带实参的 Customer 构造函数(即默认构造函数)初始化。默认构造函数将针对 name 和 lastTransaction 执行缺省的初始化动作。

在拷贝赋值操作符上只有轻微不同。它不曾企图修改其 base class 的成员变量,所以那些成员变量保持不变。

正确的做法是,让 derived class 的拷贝构造(赋值)函数调用相应的 base class 函数:

PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs)
	: Customer(rhs),  // 调用基类的拷贝构造函数
      priority(rhs.priority)
{
	logCall("PriorityCustomer copy constructor");
}
PriorityCustomer& PriorityCustoer::operator=(const PriorityCustomer& rhs)
{
	logCall("PriorityCustomer copy assignment operator");
    Customer::operator=(rhs); // 对基类成分进行赋值动作
    priority = rhs.priority;
    return *this;
}
0

评论区