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++