copying函数一般有两个:
copy 构造函数 和 copy assignment(赋值操作)
如果我们自己去实现copy而不用编译器默认的,我们就要认真复制对象的每一项,包括基类的东西。
记住:
当你编写一个copying函数,请确保
1.复制所有的local成员变量;
2.调用所有的base class内的适当的copying函数。
当这两个copying函数有近似相同的实现本体,令一个copying函数调用另一个copying函数无法让你达到你想要的目标。
令copy assignment调用copy构造函数是不合理的,因为这像试图构造一个已经存在的对象。反方向令copy构造函数调用
copy assignment操作符,同样无意义,相当于在一个未构造好的对象赋值。
消除重复代码的做法是:建立一个新的成员函数给两者调用。这样的函数往往是private而且常被命名为init。
下面写个测试例子验证上面的说法:
#include <iostream> using namespace std; class Base { public: Base() { n =10; } Base(const Base& rhs):n(rhs.n){} Base& operator=(const Base& rhs) { if(this == &rhs)// 认同测试 return *this; n = rhs.n; return *this; } void set(int t) { n=t; } void printB() { printf("B:n= %d\n", n); } virtual ~Base(){} private: int n; }; class De:public Base { public: De() { str = new char[10]; len = 10; strcpy(str, "hello"); } De(int n, char *s):len(n) { str = new char[len]; strncpy(str, s, n); } De(const De& rhs)//:Base(rhs) { len = rhs.len; str = new char[len]; memcpy(str, rhs.str , rhs.len); } De& operator=(const De& rhs) { if(this == &rhs)//认同测试 return *this; //Base::operator =(rhs); len = rhs.len; memcpy(str, rhs.str, rhs.len); return *this; } void printD() { printB(); printf("D:len= %d D:str= %s\n", len, str); } ~De() { delete str; str = NULL; } private: char *str; int len; }; int main() { De d; d.set(11); d.printD(); printf("\n"); De dd(d); dd.printD(); printf("\n"); d.set(12); dd = d; dd.printD();// return 0; }运行结果如图:
可以看出类De新的对象dd调用copy构造函数后从基类派生的值B:n 并没有改变为我们设置的新的值11.
对象d 调用函数d.set(12);把基类的成员n值设为12 然后调用 赋值操作 dd=d ,而此时对象dd从基类
派生的值 B:n依然为10,旧值。
我们依据条款12 作如下改变:
把上面的派生类De作如下改变,重新运行程序:
class De:public Base { public: De() { str = new char[10]; len = 10; strcpy(str, "hello"); } De(int n, char *s):len(n) { str = new char[len]; strncpy(str, s, n); } De(const De& rhs):Base(rhs) { len = rhs.len; str = new char[len]; memcpy(str, rhs.str , rhs.len); } De& operator=(const De& rhs) { if(this == &rhs)//认同测试 return *this; Base::operator =(rhs); len = rhs.len; memcpy(str, rhs.str, rhs.len); return *this; } void printD() { printB(); printf("D:len= %d D:str= %s\n", len, str); } ~De() { delete str; } private: char *str; int len; };
看到吗,copying真正的起作用了,在派生类中设计copying切记:
1.复制所有的local成员变量;
2.调用所有的base class内的适当的copying函数。
对应到上面的派生类De为:
De(const De& rhs):Base(rhs);
Base(rhs) Base::operator =(rhs);
REF: effective c++