引用和拷贝构造函数课件

上传人:仙*** 文档编号:241311501 上传时间:2024-06-17 格式:PPT 页数:31 大小:200KB
返回 下载 相关 举报
引用和拷贝构造函数课件_第1页
第1页 / 共31页
引用和拷贝构造函数课件_第2页
第2页 / 共31页
引用和拷贝构造函数课件_第3页
第3页 / 共31页
点击查看更多>>
资源描述
面向对象程序设计 中国科学技术大学计算机系 马建辉18.1 C+的指针和引用的指针和引用(略略)8.1.1 C+中的指针中的指针F与与C的区别:类型要求更强。的区别:类型要求更强。bird*b;rock*r;void*v;b=r;/error in C and C+v=r;b=v;/OK in C,but not in C+8.1.2 C+中的引用中的引用(续续)#include using namespace std;int y;int&r=y;/引用被创建时,必须联系到某个存储单元引用被创建时,必须联系到某个存储单元 const int&q=12;/(1)编译器分配一个存储单元,编译器分配一个存储单元,/然后然后q q跟该单元相联系跟该单元相联系int x=0;/(2)int&a=x;/(3)int main()cout x=x ,a=a endl;a+;cout x=x ,a=a endl;/:$使用引用的规则使用引用的规则(略略)1.1.当引用被创建时,它必须被初始化;当引用被创建时,它必须被初始化;2.2.一个引用被初始化为一个引用被初始化为“引用引用”某个对象,它就某个对象,它就 不能改变为另一个对象的引用不能改变为另一个对象的引用3.3.不能有不能有“空空”引用,必须保证引用是和一块合法引用,必须保证引用是和一块合法 的存储单元相联系。的存储单元相联系。n引用:就像是能引用:就像是能自动自动被编译器被编译器间接引用间接引用的的constconst指针指针。8.1.3 函数中的引用函数中的引用1.引用用作函数参数引用用作函数参数 函数中任何对引用的更改将改变被引用的实参。函数中任何对引用的更改将改变被引用的实参。问题:如何保护实参不被非法修改?问题:如何保护实参不被非法修改?2.引用用作返回值引用用作返回值 必须保证引用关联的内存是合法的。必须保证引用关联的内存是合法的。EgEg:见下页见下页例:引用作参数和返回值int*f(int*x)(*x)+;return x;/Safe,x 的作用范围在函数之外的作用范围在函数之外int&g(int&x)x+;/Same effect as in f()return x;/Safe,outside this scopeint&h()int q;/!return q;/Error static int x;return x;/Safe,x lives outside this scope例:引用作参数和返回值int main()int a=0;f(&a);/Ugly(but explicit)g(a);/Clean(but hidden)/:8.1.3 函数中的引用函数中的引用(续续)问:如何保护实参不被非法修改?问:如何保护实参不被非法修改?使用常量引用作为参数。使用常量引用作为参数。void f(X&)void g(const X&)int main()X varxobj(1);const X cnstobj(10);/!f(cnstobj);/Error g(cnstobj);/:面向对象程序设计 中国科学技术大学计算机系 马建辉98.2 拷贝构造函数拷贝构造函数形如形如 X(X&)的构造函数的构造函数.8.2.1 活动记录活动记录(Active record)(略)(略)返回值返回值(寄存器寄存器/对象地址对象地址)实在参数实在参数返回地址返回地址保存的机器状态保存的机器状态局部数据局部数据临时数据临时数据函数返回值,函数返回值,通常是对象的通常是对象的地址地址主调函数传递主调函数传递给被调函数的给被调函数的参数值参数值函数返回后的下函数返回后的下一条执行语句。一条执行语句。也指示主调函数也指示主调函数的活动记录的活动记录8.2.2 如何实现按值传递和返回值如何实现按值传递和返回值?1.1.传递和返回基本类型数据传递和返回基本类型数据 int f(int x,char c);int g=f(a,b);push b push a call f()add sp,4 mov g,register AX 把参数直把参数直接压栈接压栈从寄存从寄存器中获器中获得返回得返回值值8.2.2 如何实现按值传递和返回值如何实现按值传递和返回值?2.2.传递和返回大对象传递和返回大对象struct Big char buf50;int i;long d;B,B2;Big bigfun(Big b)b.i=100;/Do something to the argument return b;int main()B2=bigfun(B);/:8.2.2 如何实现按值传递和返回值如何实现按值传递和返回值?注注1注注2_main procnearpushbpmovbp,spmovax,offset DGROUP:_Bmovdx,dsmovcx,56call near ptr N_SPUSHpushdspushoffset DGROUP:_B2call near ptr bigfun$q3Bigadd sp,60pop bpret_main endp注:注:1.N_SPUSH1.N_SPUSH是一个把是一个把B B的的地址地址压栈的辅助压栈的辅助函数;函数;2.B22.B2的地址作为返回值也被压栈的地址作为返回值也被压栈8.2.2.1 位拷贝位拷贝 当按值传递当按值传递(或返回或返回)一个自定义对象时,编译器一个自定义对象时,编译器先把需要传递(或返回)的对象的地址压栈,然后由先把需要传递(或返回)的对象的地址压栈,然后由一个专门的辅助函数把值一个专门的辅助函数把值拷贝拷贝到目的地。拷贝的方式到目的地。拷贝的方式是按位一一对应拷贝,称为是按位一一对应拷贝,称为“位拷贝位拷贝”。Obj AObj B8.2.3 对象的初始化对象的初始化 当用一个对象去生成(初始化)另一个对象时,同样地,编当用一个对象去生成(初始化)另一个对象时,同样地,编译器并不是调用普通的构造函数生成该对象,而是以译器并不是调用普通的构造函数生成该对象,而是以位拷贝位拷贝的方式生成该对象。的方式生成该对象。X x1(0);X x2=x1;/初始化初始化,等价于等价于 X x2(x1);/按位拷贝生成按位拷贝生成X2.X2.问:位拷贝有什么问题?问:位拷贝有什么问题?答:尽管对象由一个内存区的比特位构成,但对象具有含义,答:尽管对象由一个内存区的比特位构成,但对象具有含义,因此对象远比一组比特位要复杂得多。而对象的这些含义往因此对象远比一组比特位要复杂得多。而对象的这些含义往往不能由简单的位拷贝来很好地反映。往不能由简单的位拷贝来很好地反映。例:位拷贝的缺陷#include using namespace std;class HowMany static int objectCount;public:HowMany()objectCount+;static void print(const string&msg=)if(msg.size()!=0)cout msg :;cout objectCount=objectCount endl;HowMany()objectCount-;print(HowMany();int HowMany:objectCount=0;/按值传递和返回按值传递和返回HowMany f(HowMany x)x.print(x argument inside f();return x;int main()HowMany h;HowMany:print(after construction of h);HowMany h2=h;HowMany:print(after h2=h);/:输出结果输出结果:after construction of h:objectCount=1After call to f():objectCount=1HowMany():objectCount=0HowMany():objectCount=-18.2.4 问题问题&解决解决F由于使用简单的位拷贝初始化对象,没能正确地由于使用简单的位拷贝初始化对象,没能正确地反映对象的含义,没有改变反映对象的含义,没有改变objectCountobjectCount值。值。I问:如何解决?问:如何解决?I答:定义自己的拷贝方法,而不是使用系统默认答:定义自己的拷贝方法,而不是使用系统默认的位拷贝的方式。这个方法称为类的的位拷贝的方式。这个方法称为类的“拷贝构造拷贝构造函数函数”。当从一个对象拷贝生成一个新对象时该。当从一个对象拷贝生成一个新对象时该函数被自动执行。函数被自动执行。8.2.5 拷贝构造函数拷贝构造函数因为拷贝生成对象的方式为:因为拷贝生成对象的方式为:HowmanyHowmany h2(h);h2(h);所以拷贝构造函数的形式应该为:所以拷贝构造函数的形式应该为:X(X&)X(X&);例如:例如:Howmany:Howmany(const Howmany&h)$注意:注意:1.1.参数必须是类参数必须是类howmanyhowmany的的constconst引用引用(const(const howmanyhowmany&),why?(&),why?(否则会引起无穷递归否则会引起无穷递归!)!)2.2.没有返回值。没有返回值。例:howmany2#include using namespace std;class HowMany2 string name;/Object identifier static int objectCount;public:HowMany2(const string&id=):name(id)+objectCount;print(HowMany2();HowMany2()-objectCount;print(HowMany2();/The copy-constructor:HowMany2(const HowMany2&h):name(h.name)name+=copy;+objectCount;print(HowMany2(const HowMany2&);void print(const string&msg=)const if(msg.size()!=0)cout msg endl;cout t name :objectCount=objectCount endl;int HowMany2:objectCount=0;/Pass and return BY VALUE:HowMany2 f(HowMany2 x)x.print(x argument inside f();out Returning from f()endl;return x;int main()HowMany2 h(h);out Entering f()endl;HowMany2 h2=f(h);h2.print(h2 after call to f();out Call f(),no return value endl;f(h);out After call to f()endl;/:Howmany2()h:objectCount=1Entering f()Howmany2(const Howmany2&)h copy:objectCount=2X argument inside f()h copy:objectCount=2Returning from f()Howmany2(const Howmany2&)h copy copy:objectCount=3howmany2()h copy:objectCount=2h2 after call to f()h copy copy:objectCount=2Call f(),no return valueHowmany2(const Howmany2&)h copy:objectCount=3X argument inside f()h copy:objectCount=3Returning from f()/临时对象临时对象Howmany2(const Howmany2&)h copy copy:objectCount=4 howmany2()h copy:objectCount=3 howmany2()h copy copy:objectCount=2After call to f()howmany2()/h2 h copy copy:objectCount=1howmany2()/h h:objectCount=08.2.6 默认拷贝构造函数默认拷贝构造函数F如果没有自定义拷贝构造函数,编译器生成一个默认如果没有自定义拷贝构造函数,编译器生成一个默认的拷贝构造函数(位拷贝)。的拷贝构造函数(位拷贝)。F如何替代拷贝构造函数如何替代拷贝构造函数 1.1.防止按值传递防止按值传递:声明一个私有的空拷贝构造函数声明一个私有的空拷贝构造函数 2.2.在函数中使用指针传递,而不使用引用传递在函数中使用指针传递,而不使用引用传递class Xprivate:X(const X&);X x1;X x2=x1;/error,不能调用私有成员函数不能调用私有成员函数例:例:Cstring(课堂习题课堂习题)class Cstring char*str;int sz;public:Cstring(int size)sz=size;str=new char sz;Cstring(const Cstring&obj);/;Cstring s1(10);Cstring s2(s1);Cstring:Cstring(const Cstring&obj)sz=obj.sz;str=new charsz;memcpy(str,obj.str,sz);8.3 指向成员的指针(指向成员的指针(略略)Type class_name:*pointertomember eg:P473Type(class_name:*pointertomember)(arguments_list)eg:P 475#include using namespace std;class Widget void f(int)const cout Widget:f()n;void g(int)const cout Widget:g()n;void h(int)const cout Widget:h()n;void i(int)const cout Widget:i()n;enum cnt=4;void(Widget:*fptrcnt)(int)const;public:Widget()fptr0=&Widget:f;/Full spec required fptr1=&Widget:g;fptr2=&Widget:h;fptr3=&Widget:i;void select(int i,int j)if(i=cnt)return;(this-*fptri)(j);int count()return cnt;int main()Widget w;for(int i=0;i w.count();i+)w.select(i,47);/:小结小结vC+C+的引用的引用&指针指针v拷贝构造函数拷贝构造函数v指向成员的指针(略)指向成员的指针(略)作业:作业:11.3(上机调试,出错信息是什么?)(上机调试,出错信息是什么?)11.16
展开阅读全文
相关资源
相关搜索

最新文档


当前位置:首页 > 管理文书 > 施工组织


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!