effective c++条款12:复制对象别忘其每一个成分

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;
}
运行结果如图:

effective c++条款12:复制对象别忘其每一个成分_第1张图片

可以看出类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;
};

程序运行结果如图:

effective c++条款12:复制对象别忘其每一个成分_第2张图片

看到吗,copying真正的起作用了,在派生类中设计copying切记:

1.复制所有的local成员变量;

2.调用所有的base class内的适当的copying函数。


对应到上面的派生类De为:

De(const De& rhs):Base(rhs);

  Base(rhs) Base::operator =(rhs);


REF: effective c++

你可能感兴趣的:(C++,赋值,effective,拷贝构造,条款12)