今天看《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;
};
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
#include
#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
#include
#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;
}
(完)