首页 > 代码库 > 类的三个特殊成员Copy Constructor、Copy-Assignment Operator、Destructor重载与使用

类的三个特殊成员Copy Constructor、Copy-Assignment Operator、Destructor重载与使用

今天看《C++ Primer》的13.1节——Copy, Assign, and Destroy

被这几个玩意儿弄得晕得不行:


  ◆   Copy Constructor

  ◆   The Copy-Assignment Operator

  ◆   Destructor


主要问题集中在:


  ◆   我们在什么时候需要自己重写?

  ◆   系统会在什么时候用我们重写的版本?

  ◆   拷贝构造和赋值操作符的区分到底是什么?


0x00 特性

为了区分他们,我们首先要分别从每一个的特性说起

这个可以参考 http://note.youdao.com/share/?id=04efd559b42f3672423b3a2f08c86899&type=note


0x01 把戏

上面那个链接其实可看可不看闭嘴,因为我自己总结了一遍下来,还是弄不清楚。

必须要来点儿实际的!


0x02 学习材料

非常好的实战讲解视频 https://www.youtube.com/watch?v=F-7Rpt2D-zo&noredirect=1


0x03 一个不需要自己写以上三者的场景

在游戏设计中,我们通常需要一些角色

每个角色保护自己的特性,首先我们假设有:名字生命值攻击力智力

class Character
{
public:
    Character(string name, int life, int strength, int intelligence):
      _name(name), _life(life), _strength(strength), _intelligence(intelligence){}
private:
    string _name;
    int _life;
    int _strength;
    int _intelligence;
};

如果我们需要把角色A的属性复制给角色B

int main()
{
	Character c1("Bob", 7, 5, 6);
	Character c2("Sally", 8, 6, 6);

	c1 = c2;	//调用系统装配的 Copy-Assignment Operator
}


0x04 变为需要自己写的场景

现在,我们为角色增加一项属性:物品栏



同样,把角色A的属性复制给角色B,如果我们继续使用系统默认的版本,则系统只把指针的内容拷贝给c1

至于内容嘛……共享堆上的……

c1=c2;


这种赋值称作:


危险之处在于,如果我们角色复制完成后,删除角色c2的内容,那么此时c1的工具也全没了!!!

设想这是RPG游戏的角色交易与重绑定,那么……就等着被玩家投诉死吧!!!大笑大笑大笑

#include <iostream>
#include <string>

#define TOOL_SIZE 5

using namespace std;

class Tool
{
public:
	Tool()
	{
		for (int i = 0; i < TOOL_SIZE; i++)
		{
			_tool[i] = 0;
		}
	}

	void set_tool1(int tool[TOOL_SIZE])
	{
		for (int i = 0; i < TOOL_SIZE; i++)
		{
			_tool[i] = tool[i];
		}
	}
private:
	int _tool[TOOL_SIZE];
};

class Character
{
public:
	Character(string name, int life, int strength, int intelligence, Tool* toolArray):
	  _name(name), _life(life), _strength(strength), _intelligence(intelligence), _toolArray(toolArray){}

private:
	string _name;
	int _life;
	int _strength;
	int _intelligence;
	Tool* _toolArray;
};

int main()
{
	Tool *t1 = new Tool;	
	int tool1[5] = {11,0,0,0,0};
	t1->set_tool1(tool1);

	Tool *t2 = new Tool;	
	int tool2[5] = {21,22,23,0,0};
	t2->set_tool1(tool2);

	Character c1("Bob", 7, 5, 6, t1);
	Character c2("Sally", 8, 6, 6, t2);

	c1 = c2;			//调用系统装配的 Copy-Assignment Operator
	Character c3 = c2;	//调用系统装配的 Copy Constructor

	return EXIT_SUCCESS;
}


A: 如果我们想通过

c1=c2;
得到如下结果就要重载 opreator=


B: 如果我们想通过

Character c3 = c2;
得到如下结果就要重载 拷贝构造函数

WHY? 因为 opreator= 仅在对象已存在时调用!



前面还提到了删除角色c2的问题,如果我们用了完全拷贝,那么删除时如果用系统装配的析构函数,会产生垃圾


此时,就需要自己写Destructor来delete他们


综上,为了漂亮地完成游戏角色的复制、删除问题:



而这,恰好就是 Rule of Three.

#include <iostream>
#include <string>

#define TOOL_SIZE 5

using namespace std;

class Tool
{
public:
	Tool()
	{
		for (int i = 0; i < TOOL_SIZE; i++)
		{
			_tool[i] = 0;
		}
	}

	Tool(const Tool &t)
	{
		for (int i = 0; i < TOOL_SIZE; i++)
		{
			_tool[i] = t._tool[i];
		}
	}

	void set_tool(int tool[TOOL_SIZE])
	{
		for (int i = 0; i < TOOL_SIZE; i++)
		{
			_tool[i] = tool[i];
		}
	}

	int get_tool(int index)
	{
		return _tool[index];
	}
private:
	int _tool[TOOL_SIZE];
};

class Character
{
public:
	Character(string name, int life, int strength, int intelligence, Tool* toolArray):
	  _name(name), _life(life), _strength(strength), _intelligence(intelligence), _toolArray(toolArray){}

	Character(const Character &c):
	  _name(c._name), _life(c._life), _strength(c._strength), _intelligence(c._intelligence), _toolArray(new Tool(*(c._toolArray)))
	{
		cout << "Copy Constructor Called!\n";
	}

    Character& operator=(const Character &c)
	{
		_name			= c._name;
		_life			= c._life;
		_strength		= c._strength;
		_intelligence	= c._intelligence;
		_toolArray		= new Tool(*(c._toolArray));

		cout << "Copy-Assignment Operator Called!\n";
		return *this;
	}

	Tool* get_tool_array()
	{
		return _toolArray;
	}

	~Character()
	{
		delete _toolArray;
	}

private:
	string _name;
	int _life;
	int _strength;
	int _intelligence;
	Tool* _toolArray;
};

int main()
{
	Tool *t1 = new Tool;	
	int tool1[5] = {11,0,0,0,0};
	t1->set_tool(tool1);

	Tool *t2 = new Tool;	
	int tool2[5] = {21,22,23,0,0};
	t2->set_tool(tool2);

	Character c1("Bob", 7, 5, 6, t1);
	Character c2("Sally", 8, 6, 6, t2);

	c1 = c2;			//调用系统装配的 Copy-Assignment Operator
	Character c3 = c2;	//调用系统装配的 Copy Constructor

	return EXIT_SUCCESS;
}



(完)


类的三个特殊成员Copy Constructor、Copy-Assignment Operator、Destructor重载与使用