设计良好的面向对象系统会将对象的内部封装起来,指留下两个函数负责对象拷贝,那便是带着适切名称的copy构造函数和copy assignment操作符,我们称它们为copying函数。
考虑一个类用来表示顾客,手工写出copying函数:
- void logCall(const std::string& funName);//构造一个log entry
- class Customer
- {
- public:
- ...
- Customer(const Customer& rhs);
- Customer& operator=(const Customer& rhs);
- ...
- 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:
- ... //同前
- private:
- std::string name;
- Date lastTransaction;
- };
这时候copying执行的是局部拷贝:它们的确复制了顾客的name,但是没有赋值新添加到lastTransaction,大多数编译器对此不出任何警告。如果你为class添加了一个成员变量,你必须同时修改copying函数。
如果继承,可能会造成一个潜在危机:
- class PrioCustomer:public Customer
- {
- public:
- ...
- PrioCustomer(const PrioCustomer& rhs);
- PrioCustomer& operator=(const PrioCustomer& rhs);
- ...
- private:
- int prio;
- };
- PrioCustomer::PrioCustomer(const PrioCustomer& rhs):prio(rhs.prio)
- {
- logCall("PrioCustomer copy constructor");
- }
- PrioCustomer& PrioCustomer::operator=(const PrioCustomer& rhs)
- {
- logCall("PrioCustomer copy assignment operator");
- prio = rhs.prio;
- return *this;
- }
看起来好像是复制了PrioCustomer内的每一个数据,但每个PrioCustomer还内含它所继承的Customer成员变量,而那些变量却未被赋值。
应该让继承类的copying函数调用相应的基类函数:
- PrioCustomer::PrioCustomer(const PrioCustomer& rhs)
- :Customer(rhs),prio(rhs.prio)
- {
- logCall("PrioCustomer copy constructor");
- }
- PrioCustomer& PrioCustomer::operator=(const PrioCustomer& rhs)
- {
- logCall("PrioCustomer copy assignment operator");
- Customer::operator=(rhs);
- prio = rhs.prio;
- return *this;
- }
当你编写一个copying函数,请确保:复制所有local成员变量,调用所有基类内的适当的copying函数。
令copy assignment操作符调用copy构造函数是不合理的。
令copy构造函数调用copy assignment操作符也是不合理的。
如果你发现你的copy构造函数和copy assignment操作符有相近的代码,消除重复代码的做法是,建立一个新的成员函数给两者调用,这样的函数往往是private而且常被命名为init。
1.Copying函数应该确保复制“对象内的所有成员变量”及“所有基类成分”
2.不要尝试以某个copying函数实现另一个copying函数,应该将共同机能放在第三个函数中,并由两个copying函数共同调用。