Copy all parts of an object
copy构造函数和copy assignment操作符对一个类型的实例进行了copying。即使不刻意去编写,编译器一样会尽力相助。当你不需要编译器的好心相助时,也许会得到它的报复。假设字定义一个类型,并且实现了自己的copy构造函数和copy assignment:
class X {
public:
X() : _size(0) { }
virtual ~X() { }
X(const X& rhs);
X& operator=(const X& rhs);
int GetSize(void) const { return _size; }
private:
int _size;
};
X::X(const X &rhs) {
this->_size = rhs.GetSize();
}
X& X::operator=(const X& rhs) {
if (this == &rhs)
return *this;
this->_size = rhs.GetSize();
return *this;
}
现在X类型实现了自己的copy构造函数和copy assignment操作符,但如果当X类型又多了一个成员变量的时候,再编译时候编译器不会提醒我们当前X类型并没有实现所谓的Copy all parts of an object。这往往是违背了Copying函数原则的事情。
又如果X还有其派生类型,那么派生类型又没有做到这些事,编译器也懒的想提醒你。
class XX : public X {
public:
XX() : X(), _size2(0) { }
~XX() { }
XX(const XX& rhs);
XX& operator=(const XX& rhs);
int GetSize2(void) const { return _size2; }
private:
int _size2;
};
XX::XX(const XX& rhs) {
this->_size2 = rhs.GetSize2();
};
XX& XX::operator=(const XX& rhs) {
if (this == &rhs)
return *this;
this->_size2 = rhs.GetSize2();
return *this;
}
基类型X的成员变量没有得到copying动作,为了承担起这份责任,必须调用基类型的copy构造函数以几copy assignment操作符。
XX::XX(const XX& rhs) : X(rhs) {
this->_size2 = rhs.GetSize2();
};
XX& XX::operator=(const XX& rhs) {
if (this == &rhs)
return *this;
X::operator=(rhs);
this->_size2 = rhs.GetSize2();
return *this;
}
所谓的复制每一个部分已经很清楚了,复制每一个当前类型内的成员变量,并调用基类型提供的copying函数。给一个建议,最好不要在copy assignment操作符里调用copy构造函数,这不是什么省事的动作,等同于构造了已经存在的对象。同样反会来在copy构造函数里调用copy assignment操作符也一样很无聊,copy构造函数是构造一个新的对象,而copy assignment操作符则是用于已经被构造过的对象上。
copy assignment操作符调用copy构造函数
XX& XX::operator=(const XX& rhs) {
if (this == &rhs)
return *this;
return XX(rhs);
}
copy构造函数调用copy assignment操作符
XX::XX(const XX& rhs) {
const_cast<XX*>(this) = &XX::operator =(rhs);
}
需要记住的
l 要确保拷贝函数拷贝对象的所有的数据成员,及其基类的所有部分,不要有遗漏。
l 不要尝试去实现一个拷贝函数来供其它的拷贝函数调用。取而代之的是,把公共部分放入一个“第三方函数”中共所有拷贝函数调用。