首页 > 代码库 > 类的三个特殊成员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重载与使用