类的三个特殊成员Copy Constructor、Copy-Assignment Operator、Destructor重载与使用
2014-09-28 20:53
218 查看
今天看《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 一个不需要自己写以上三者的场景
在游戏设计中,我们通常需要一些角色
每个角色保护自己的特性,首先我们假设有:名字,生命值,攻击力,智力
如果我们需要把角色A的属性复制给角色B
0x04 变为需要自己写的场景
现在,我们为角色增加一项属性:物品栏
同样,把角色A的属性复制给角色B,如果我们继续使用系统默认的版本,则系统只把指针的内容拷贝给c1
至于内容嘛……共享堆上的……
这种赋值称作:
危险之处在于,如果我们角色复制完成后,删除角色c2的内容,那么此时c1的工具也全没了!!!
设想这是RPG游戏的角色交易与重绑定,那么……就等着被玩家投诉死吧!!!
A: 如果我们想通过
B: 如果我们想通过
WHY? 因为 opreator= 仅在对象已存在时调用!
前面还提到了删除角色c2的问题,如果我们用了完全拷贝,那么删除时如果用系统装配的析构函数,会产生垃圾
此时,就需要自己写Destructor来delete他们
综上,为了漂亮地完成游戏角色的复制、删除问题:
而这,恰好就是 Rule of Three.
(完)
被这几个玩意儿弄得晕得不行:
◆ 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; }
(完)
相关文章推荐
- linux三个特殊权限setuid、setgid和stick bit使用详解
- Item 22: 当使用Pimpl机制时,在实现文件中给出特殊成员函数的实现
- 函数指针数组的应用,但在类内作为成员使用,需要特殊处理,指针类型要匹配
- Item 22: 当使用Pimpl机制时,在实现文件中给出特殊成员函数的实现
- linux三个特殊权限setuid.setgid和stick bit使用详解
- 单目运算符重载为成员函数 前++ 和后++的使用
- oc82--成员变量使用copy修饰
- linux三个特殊权限setuid、setgid和stick bit使用详解
- 第十七章 特殊成员_使用typedef简化函数指针的声明
- Effective Modern C++ 条款22 当使用Pimpl Idiom时,在实现文件中定义特殊成员函数
- C++的一些基本功,包括对常量成员函数的一些特殊说明
- 使用PB调用API自动更新(非FTP模式)(三、连接函数F_CONNECT_COPYSERVER)
- Ado的特殊使用方法
- 值类型局部变量必须先初始化才能使用,值类型成员变量可以不初始化。
- 重载的使用(C++)
- vi 使用技巧(二): copy, paste, delete, 块编辑,redo/undo
- 第17章 特殊成员函数
- 重载成员函数使CAsyncSocket类支持IPX/SPX协议
- 使用copy出现的问题
- 在JScript面向对象编程中使用重载(续)