已阅读5页,还剩4页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
类的构造函数、析构函数、复制构造函数和赋值操作符作者:lyb661 时间:20140318首先,回顾一下有关函数的知识。函数声明一般由三个部分组成:返回类型、函数名和由圆括号括起来的参数表。(1)函数可以没有返回类型,这时返回类型由void表示;(2)函数名标志函数的接口,也是与其他函数区别的标志;(3)函数可以没有参数,也可以有一至多个参数;(4)可以根据参数类型、数量的差别重载函数。例如:int sum(int a,int b);void write(char c);void display()const;重载函数的例子:void swap(int x,int y);void swap(double x,double y);上面是一些带有内置类型参数的函数的例子。类类型同样有与自己相关的函数。其中有几个特殊的成员函数,对类来说至为重要。1、类的构造函数(consructor):构造函数用于创建类对象时完成必要的初始化工作。所有的类都需要构造函数。它没有返回类型,函数与类同名,可以没有,也可以有多个参数,如果必要。/【例1】Data_class1#includeusing std:cout;using std:endl;class Data int value;public: Data(int initial=0):value(initial) /构造函数constructor int read()constreturn value; void write(int i)value=i;int main() Data a(10); couta.read()endl;/10 Data b; coutb.read()endl;/0 b.write(20); coutb.read()endl;/20 return 0;运行结果:10020/关于构造函数有以下几点:(1)对于任何类,编译器会自动调用一个默认的构造函数;(2)如果定义了自己的构造函数,则默认的构造函数将不再工作;(3)同一般的函数一样,构造函数也可以被重载。(4)可以定义默构造函数,如编译器合成的那样工作。Data(int initial=0):value(initial)就是一个重载的有默认值的构造函数。当创建对象a(10)时只有调用它才能正常工作。注意到该构造函数的参数有个默认值0。如果没胡这个0,则对象b就不能被建立。它代替默认构造函数的部分工作。对于这个简单的Data类,它的默认构造函数应该是这样:Data()。这个由编译器合成的构造函数用于创建一个对象而不显式地初始化。如果用这个默认构造函数替换我们自己定义的构造函数,则a对象的建立是无效的,而对象b的成员初始值是无定义的,有兴趣的话可以自己试一试。当然,也可以用成员函数read()来完成一些初始化工作。总之,像这样一个简单的类,默认构造函数的工作也不是尽如人意的。对于复杂一点的类呢?/【例2】Data_class2(警告:本程序有内存泄漏风险不要上机运行)#includeusing std:cout;using std:endl;class Data int *ip;public: Data(int &i):ip(new int(i) Data()delete ip; /destructor int read()constreturn *ip; void write(int n)*ip=n;int main() int obj=10; Data a(obj); couta.read()endl; Data b=a; coutb.read()endl; return 0;/本例是上一例的改进,由于类具有指针成员,并且申请自由存储,所以重新定义了析构函数的行为,用于删除指针。2、类的析构函数(destructor) :析构函数与类同名,在名字前加符号以与构造函数相区别。析构函数用于在类对象超出作用域时按类中声明次序的逆序撤销各个成员。与构造函数有所不同:尽管类定义了自己的析构函数,编译器合成的析构函数也会正常工作。由于函数重载规则的限制,析构函数是不能被重载的。为什么?我们所谓自定义的意思,不过在它常规工作量外给它加了点的担子。对于上面的Data类来说,它的默认的析构函数Data()的工作并不能令人满意。该类有一个int类型的指针成员,在程序运行过程中由该指针申请了自由存储,所以必须定义一个析构函数,在程序结束后删除指针,进而撤销自由存储。这个工作默认的析构函数是不能胜任的。本程序潜在的风险当然还不只这些。当对象b建立的时候,b从a复制了指针成员。由于只是复制指针的值,这两个指针共享一个int变量。因为析构对象与创建对象的顺序相反,后建立的对象首先被析构(“后进先出”last int first out)。当析构函数将b的指针删除,然后这个int变量也将撤销,致使a的指针不再指向任何对象,而成了悬垂指针。而当这个指针被删除时,同一块内存撤销了两次,内存泄漏的风险就在这里。一般将上述复制行为称为浅复制,而规避风险的办法就是定义一个复制构造函数来完成深层复制。/【例3】Data_class3#includeusing std:cout;using std:endl;class Data int *ip;public: Data(int &i):ip(new int(i) Data()delete ip; Data(const Data&); int read()constreturn *ip; void write(int n)*ip=n;Data:Data(const Data &dt) ip=new int(*dt.ip);int main() int obj=10; Data a(obj); couta.read()endl; Data b=a; coutb.read()endl; b.write(20); couta:a.read(),b:b.read()endl; return 0;运行结果:1010a:10,b:20/3、类的复制构造函数(copy constructor)从上边运行结果,a与b的指针成员不同,指向的变量也不同,复制后各归各家,不再纠缠不清。Data:Data(const Data &dt);就是所谓的复制构造函数。它也与类同名,参数是同类的常引用。与默认构造函数一样,复制构造函数可由编译器隐式调用。也就是说第例2的程序中,编译器合成了复制构造函数,只是不能有效工作罢了。与合成的默认构造函数不同,即使我们定义了其他构造函数,也会合成复制构造函数。合成复制构造函数的行为是,执行逐个成员初始化,将新对象初始化为原对象的副本。这说明了复制构造函数也不能重载的。不过,我们可以通过编写代码,来规定构造函数的行为,令其有效地工作。例2中的复制构造函数之所以不能有效地工作,是因为它是浅复制,只复制指针的值,而不涉及指针指向的对象。有另外的办法来规避内存泄漏的风险,就是对类的指针成员进行引用计数,当指针的引用计数多于1时绝不删除指针,只当引用计数为1,也就是最后一个指针时才删除指针,这就是所谓智能指针。这略复杂些,稍后再讨论。上边例3实际还有风险存在。/【例4】Data_class4#includeusing std:cout;using std:endl;class Data int *ip;public: Data(int i=0):ip(new int(i)/constructor /Data() /default constructor Data()delete ip; /destructor Data(const Data&);/copy constructor Data &operator=(const Data&); /assignment operator int read()constreturn *ip; void write(int n)*ip=n;Data:Data(const Data &dt) ip=new int(*dt.ip);Data &Data:operator=(const Data &dt) if(this!=&dt) *ip=*dt.ip; return *this;int main() int obj=10; Data a(obj); couta.read()endl; Data b=a; coutb.read()endl; b.write(20); Data c; c=b;/ uses assignment operator c.write(30); couta:a.read(),b:b.read(),c:c.read()endl; return 0;运行结果1010a:10,b:20,c:30/例4又增加一个赋值操作符。因为类Data中有赋值工作:c=b。如果像常规那样进行赋值,内存泄漏的风险依然存在。4、类的赋值操作符(assignment operator) :赋值操作符是类成员函数重载操作符的一个的例子。它使应用于一般内置变量的赋值操作符=一样应用于类对象。就是说,我们可以将一个类对象赋给另一个同类的对象,而它们成员之间的赋值行为将由我们编写的代码来规定。与复制构造函数一样,如果类没有定义自己的赋值操作符,则编译器会合成一个。类也可以定义自己的赋值操作符。一般而言,如果类需要复制构造函数,它也会需要赋值操作符,同时也需要析构函数。本例中,默认的赋值操作符不能正常工作,默认的赋值操作符,只复制了指针的值,还属于浅复制。赋值符两边对象的指针纠缠在一起。Data &Data:operator=(const Data &dt) ip=dt.ip; return *this;只有重新定义赋值操作符,才能进行深复制。Data &Data:operator=(const Data &dt) if(this!=&dt) *ip=*dt.ip; return *this;1、首先用条件语句if(this!=&dt)检验左右操作数是否相同,避免自我赋值;2、然后通过语句*ip=*dt.ip;完成深复制;3、最后返回调用对象。我们的复制控制技术,属于C+Primer所谓的值语义:值型副本是独立的:对副本的改变不会影响原有对象。如果使用计数与共享对象一起存储。需要创建一个单独类指向共享对象并管理使用计数。使用辅助类来管理指针,即智能指针技术。这项技术本身并不复杂,由于篇幅所限,将在以后讨论。最后,我们用另一段代码来验证本文所阐述的技术,做为结尾。/【例5】Data_class5#includeusing std:cout;using std:endl;class Data int *ip; static int count;public: Data(int *i):ip(new int(*i)+count;/constructor Data():ip(NULL)+count; /default constructor Data()coutcountn;-count;delete ip; /destructor Data(const Data&);/copy constructor Data &operator=(const Data&); /assignment operator int read()constreturn *ip; void write(int n)*ip=n;int Data:count=0;Data:Data(const Data &dt) ip=new int(*dt.ip); +count;Data &Data:operator=(const Data &dt) if(this=&dt) return *this; delete ip; ip=new int(*dt.ip); return *this;int main() int obj=10; Data a(&obj); couta.read()endl; Data b=a; coutb.read()endl; b.write(20); Data c; c=b;/ uses assignment operator c.write(3
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 川教版(2019)小学信息技术三年级下册第一单元第4节《网上观看大熊猫》教学设计及反思
- Unit 5 Poems Learning About Language 教学设计-2023-2024学年高中英语人教版(2019)选择性必修第三册
- 2026年甲流考试题及答案
- 第1节《做好自我管理》教学设计+教案三年级下册信息科技川教版
- 2026年义务教育历史课程标准2026年版考试测试题库及答案
- 2026年心肺复苏理论考试试题及答案
- 2026年四川省机关事业单位考调、选调工作人员考试(综合应用能力测试)全真模拟试题及答案
- 电力系统的安全与防护策略指南
- 2025-2026学年玉女心金片段教学设计
- 八年级历史下册 第三学习主题 建设中国特色社会主义 第7课 伟大的历史转折教学设计2 川教版
- 法律法规及其他要求清单-职业健康安全2026年1月版
- 加油站紧急疏散预案(6篇)
- 防洪防汛桌面演练
- 火灾现场勘验规则 XF839-2009
- 汽车使用性能与检测(第三版)全套课件
- MOOC 信息社会与人工智能-山东大学 中国大学慕课答案
- 中华传统文化与人生修养智慧树知到期末考试答案章节答案2024年四川大学
- 云南中云勐滨糖业有限公司日处理甘蔗4200吨生产线技改项目环评报告
- NB-T 10207-2019 风电场工程竣工图文件编制规程
- 如愿二声部合唱简谱文档
- GB/T 2888-2008风机和罗茨鼓风机噪声测量方法
评论
0/150
提交评论