条款12:赋值对象时勿忘其每一个成分
C++中设计良好的对象系统会将对象的内部封装起来,只留下两个函数负责对象那个拷贝(赋值),即copy构造函数和copy operator=。
如果我们自己声明自己的copying函数,则C++的编译器则不会对我们自己提供的copying函数进行检验,即使copying函数出错了编译器并不会报错。
具体参看如下代码:
class A{
public:
A(const A&);
A& opreator=(const A&);
...
private:
std::string A_a;
}
A::A(const A&a){
this->A_a=a->A_a;
}
A& A::operator::=(const A& a){
if(this==&a) return *this;
this->A_a=a->A_a;
return *this;
}
可是如果此时我们将A中加入新的变量呢?
class B{};
class A{
public:
...
private:
std::string A_a;
B b;
}
这时候,copying构造函数只是简单的复制了A_a,对于b成员变量并没有进行复制,大多数编译器无法检测出这些问题,因此,我们必须:
1)如果我们为类添加一个成员变量,必须同时修改copying函数,同时包括构造函数和一些非标准的operator=函数;
如果发生继承呢?
class A{
public:
...
A(const A&a);
A& operator=(const A&a);
private:
std::string name;
}
class B:public A{
public:
...
B(const B&b);
B& operator=(const B&b);
private:
int x;
}
B::B(const B&b):A(b){
...
}
B& B::operator=(const B&b){
A::operator=(b);
this->x=b.x;
return *this;
}
2)可以发现对于继承体系中,当你编写子类的copying函数,请确保
- 列表内容
- 复制所有local成员变量 ,同时调用所有的base classes中适当的copying函数
PS:注意此时不能用copy与构造函数调用copy assignment运算,同时copy assignment也不能调用copy构造函数,不合理,因为这样相当于试图调用一个已经存在的对象;
总结:
1)copying函数应该确保赋值“对象内的所有成员变量”和“所有基类成分”;
2)不要尝试以某个copying函数实现另一个copying函数,应该共同放在第三个函数中,并有两个copying函数调用。