第4讲 构造函数 、析构函数、this指针、静态成员PPT学习课件_第1页
第4讲 构造函数 、析构函数、this指针、静态成员PPT学习课件_第2页
第4讲 构造函数 、析构函数、this指针、静态成员PPT学习课件_第3页
第4讲 构造函数 、析构函数、this指针、静态成员PPT学习课件_第4页
第4讲 构造函数 、析构函数、this指针、静态成员PPT学习课件_第5页
已阅读5页,还剩87页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第四讲,武汉大学赵小红,面向对象程序设计,1,面,主要内容,构造函数析构函数this指针静态成员,2,面向对象程序设计,面,知识回顾,类是现实世界或思维世界中的实体在计算机中的反映,它将数据以及这些数据上的操作封装在一起。对象是具有类类型的变量。类是对象的抽象,而对象是类的具体实例。类是抽象的,不占用内存,而对象是具体的,占用存储空间。,3,面,类和对象应用举例,设计一个学生成绩的简单管理程序,输入学生的3门课成绩后,计算平均成绩,并在屏幕上输出。,学生类:数据成员:姓名,三门课成绩,平均成绩成员函数:设置姓名的函数,设置三门课程的函数,求平均的函数,输出函数。,4,面,#include#includeusingnamespacestd;constintnum_score=3;classCSTUprivate:charm_name12;floatm_scorenum_score;floatm_ave;public:voidsetname(charname);voidsetscores(floatscore);floatcalave();voidshow();,5,面,voidCSTU:setname(charname)strcpy(m_name,name);voidCSTU:setscores(floatscore)for(inti=0;inum_score;i+)m_scorei=scorei;,6,面,floatCSTU:calave()m_ave=0;for(inti=0;inum_score;i+)m_ave+=m_scorei;m_ave=m_ave/num_score;returnm_ave;voidCSTU:show()coutname:m_nameave=m_avescorei;s.setname(name);s.setscores(score);s.calave();s.show();,对一名学生成绩的处理,8,面,voidmain()CSTUs10;for(inti=0;iname;coutscorei;si.setname(name);si.setscores(score);si.calave();for(i=0;in;CSTU*s=newCSTUn;for(inti=0;iname;coutscorei;si.setname(name);si.setscores(score);si.calave();for(i=0;iname;coutscore0score1score2;s.setname(name);s.setscores(score);s.calave();s.show();,11,C,问题:structSTUcharm_name12;floatm_score3;floatm_ave;STUemployee1=LiMing,score0,score1,score2;,12,面,voidmain()CSTUs;charname12;floatscorenum_score;coutname;coutscore0score1score2;s.setname(name);s.setscores(score);s.calave();s.show();,CSTUs(name,score);,如何进行成员变量的初始化?,?,13,C,构造函数,定义类时不能对成员变量进行初始化。-只能在声明对象之后进行初始化。例如:CSTUs1;成员变量一般都定义为私有属性,不能在声明对象后利用赋值运算对成员变量进行初始化。-与struct不同,14,C,什么是构造函数,构造函数是一种与类名相同的特殊成员函数,在创建类对象时(声明或new动态创建)系统将自动调用的成员函数。,CSTUs1;CSTU*m_s=newCSTU10;CSTU*m_s2=newCSTU;CSTU*m_s3;m_s3=newCSTU;,每个对象声明语句都隐式调用了构造函数,15,C,关于构造函数的规定,构造函数的名称与类名相同;构造函数不能指定任何返回值类型,包括void返回类型。函数体内也不允许返回值,但允许用无值返回语句“return”(它的返回类型隐含为指向类对象本身的指针this)构造函数可以有参数也可以无参数。,16,面,classCSTUprivate:charm_name12;floatm_scorenum_score;floatm_ave;public:CSTU(charname,floatscore)strcpy(m_name,name);for(inti=0;inum_score;i+)m_scorei=scorei;,17,面,classCSTUprivate:charm_name12;floatm_scorenum_score;floatm_ave;public:CSTU()CSTU(charname)strcpy(m_name,name);,CSTU(charname,floatscore)strcpy(m_name,name);for(inti=0;inum_score;i+)m_scorei=scorei;,构造函数重载,18,C,关于构造函数的规定,构造函数的名称与类名相同;构造函数不能指定任何返回值类型,包括void返回类型。函数体内也不允许返回值,但允许用无值返回语句“return”(它的返回类型隐含为指向类对象本身的指针this)构造函数可以有参数也可以无参数。构造函数可以放在类的外部定义,但也要象其他成员函数一样在函数名前加上“类名:”。,19,面,classCSTUprivate:charm_name12;floatm_scorenum_score;floatm_ave;public:CSTU(charname,floatscore);CSTU:CSTU(charname,floatscore)strcpy(m_name,name);for(inti=0;inum_score;i+)m_scorei=scorei;,20,C,关于构造函数的规定,构造函数的名称与类名相同;构造函数不能指定任何返回值类型,包括void返回类型。函数体内也不允许返回值,但允许用无值返回语句“return”(它的返回类型隐含为指向类对象本身的指针this)构造函数可以有参数也可以无参数。构造函数可以放在类的外部定义,但也要象其他成员函数一样在函数名前加上“类名:”。如果一个类对象是另一个类的数据成员,则在那个类的对象创建时除了调用自己的构造函数外,还会自动调用成员(对象)的构造函数。,21,C,构造函数举例,classAPublic:A()cout“构造A”;classBPublic:Aa;B()cout“构造B”;voidmain()Bb;,运行结果:构造A构造B,22,C,默认构造函数,默认构造函数(defaultconstructor)就是在没有显式提供初始化式时调用的构造函数。它由不带参数的构造函数,或者为所有的形参提供默认实参的构造函数定义。在类定义时若没有定义任何构造函数,编译器自动生成一个不带参数的默认构造函数。当用户定义任何一个构造函数后,该默认构造函数自动消失。在定义对象时,若没有指定参数,将调用默认构造函数。,23,C,默认构造函数举例,#includeclassAprivate:intm_x;intm_y;public:A()cout不带参数构造Aendl;A(intx,inty)m_x=x;m_y=y;cout带参数构造Aendl;,运行结果:不带参数构造A带参数构造A,voidmain()Aa1;Aa2(2,5);,24,C,问题一:程序运行结果是什么?,#includeclassAprivate:intm_x;intm_y;public:A(intx,inty)m_x=x;m_y=y;cout带参数构造Aendl;,voidmain()Aa1;Aa2(2,5);,程序编译错误!原因:有了自定义的构造函数之后,编译器就不再生成默认构造函数了。,25,C,问题二:程序运行结果是什么?,#includeclassAprivate:intm_x;intm_y;public:A()cout不带参数构造Aendl;,voidmain()Aa1;Aa2(2,5);,26,C,引例,classAPublic:int*m_ip;A();A:A()m_ip=newint;,这样做有没有问题?,?,voidmain()Aa;,27,C,析构函数,一个类可能在构造函数里分配资源,这些资源需要在对象不复存在以前被释放。例如:如果构造函数打开了一个文件,文件就需要被关闭;构造函数从堆里分配了内存,这块内存也必须在对象消失前被释放。析构函数允许类自动完成这些清理工作,它是一种特殊的成员函数,它是在对象生存期结束时系统自动调用的成员函数。,28,C,析构函数举例,classXYZpublic:XYZ()name=newchar20;XYZ()deletename;protected:char*name;,29,C,关于析构函数的规定,析构函数的名称必须在类名前加上“”符号。析构函数不能指定任何返回值类型,包括void返回类型。析构函数没有参数,不能随意调用,也没有重载。它只能在类对象生命周期结束时,由系统自动调用。析构函数以调用构造函数相反的顺序被调用。,30,C,例为类Point添加构造函数和析构函数。,#includeusingnamespacestd;classPointpublic:Point(intxx=0,intyy=0);/构造函数Point();/析构函数private:intX,Y;,31,C,构造函数和析构函数的实现,Point:Point(intxx,intyy)X=xx;Y=yy;coutTheconstructorbecalled:X,Yendl;Point:Point()coutThedestructorbecalled:X,Yradius;/声明Circle对象CirclePool(radius);CirclePoolRim(radius+3);,39,C,floatFenceCost,ConcreteCost;/计算栅栏造价并输出FenceCost=PoolRim.Circumference()*FencePrice;coutFencingCostis¥FenceCostendl;/计算过道造价并输出ConcreteCost=(PoolRim.Area()-Pool.Area()*ConcretePrice;coutConcreteCostis¥ConcreteCostendl;运行结果Entertheradiusofthepool:10FencingCostis¥2858.85ConcreteCostis¥4335.39,40,面,指出下面程序中的错误并改正,classApublic:intgetS()returns;private:ints;voidmain()Aa1;a1.s=3;intt=getS();,注意:类的私有成员和公有成员的用法,41,面,指出下面程序中的错误并改正,#includeclassCpublic:voidC()s=0;cout构造函数;intgetS()returns;voidC()cout析构函数;private:ints;,注意:构造和析构函数的语法规则,42,C,拷贝构造函数,可以用一个对象构造另一个对象,或者用一个对象值初始化新构造的对象。例如:Students1(“Jenny”);Students2=s1;/用s1的值去初始化s2对象作为函数参数传递时,也涉及到对象的拷贝。例如:voidfn(Studentfs)/.voidmainStudentms;fn(ms);,43,C,为什么要用拷贝构造函数,inta=5;intb=a;/用a的值拷贝给新创建的b对象为什么不能这么拷贝呢?,44,C,为什么要用拷贝构造函数,classXYZpublic:XYZ()XYZ(intn)name=newcharn;XYZ()deletename;protected:char*name;;voidmain()XYZs(20);XYZt;t=s;,s对象,t对象,资源,45,C,为什么要用拷贝构造函数,对象不像基本数据类型那么简单,有些对象申请了资源,如果仅仅只是二进制内存空间上的s拷贝,t也会拥有这个资源,从而导致资源归属权不清,引起资源管理混乱。,46,C,拷贝构造函数,拷贝构造函数是一种特殊的构造函数,其形参为本类的对象引用。class类名public:类名(形参);/构造函数类名(类名Y=yy;Point(Point,Point:Point(Point,48,C,拷贝构造函数举例,当用类的一个对象去初始化该类的另一个对象时系统自动调用拷贝构造函数实现拷贝赋值。intmain()PointA(1,2);PointB(A);/拷贝构造函数被调用coutB.GetX()endl;,49,C,拷贝构造函数举例,若函数的形参为类对象,调用函数时,实参赋值给形参,系统自动调用拷贝构造函数。例如:voidfun1(Pointp)coutp.GetX()endl;intmain()PointA(1,2);fun1(A);/调用拷贝构造函数,50,C,拷贝构造函数举例,当函数的返回值是类对象时,系统自动调用拷贝构造函数。例如:Pointfun2()PointA(1,2);returnA;/调用拷贝构造函数intmain()PointB;B=fun2();,51,C,如果程序员没有为类声明拷贝初始化构造函数,则编译器自己生成一个拷贝构造函数。这个构造函数执行的功能是:用作为初始值的对象的每个数据成员的值,初始化将要建立的对象的对应数据成员。,52,C,引例,#includevoidfun()/静态变量a是局部变量,但具有全局的生存期staticinta=5;a+;couta=aendl;voidmain()for(inti=0;i2;i+)fun();,程序输出:a=6a=7,53,C,静态成员,静态成员分为静态数据成员和静态成员函数。静态数据成员类似于一般的static静态变量,它具有全局性。静态数据成员属于整个类,为类的所有对象共享。无论类的对象有多少,类的静态数据成员只有一份,存储在同一个内存空间。即使没有创建类的一个对象,类的静态数据成员也是存在的。使用静态数据成员保证了该数据成员值的唯一性。,54,C,static,类所创建的所有对象共享静态成员的一个拷贝。静态成员属于类,不属于类的对象,55,C,静态数据成员,静态成员的声明:放在类定义的内部在声明成员时以关键字static开头,例如:public:staticintm_nCount;,56,C,静态数据成员,静态数据成员的赋值必须放在类外的全局范围内进行,不能在构造函数中对其进行赋初值。在类的外部赋初值时,必须同时指明数据类型和所属的类。静态成员的初始化举例:intPerson:m_nCount=0;,57,C,静态数据成员的访问,公有静态成员:三种方式(1)通过对象访问,如:person1.m_nCount=100;(2)利用类名和作用域限定符(:)访问,如:intPerson:m_nCount=100;/初始化(3)在成员函数中访问,如:m_nCount+;私有和保护静态成员:只能在成员函数中访问,58,C,静态成员函数,成员函数也可以是静态的,其声明方式与静态成员变量类似。如:public:staticintGetCount();/获取静态数据成员静态成员函数也与一个类相关联,而不只与一个特定的对象相关联。区别于非静态成员函数,静态成员函数没有this指针,因为类的静态成员函数只有一个运行实例。静态成员函数一般是公有属性,可以通过对象、类名和作用域限定符、在成员函数中三种方式调用静态成员函数。-与公有属性的静态数据成员类似。,59,C,例静态成员变量和静态成员函数的使用,#include#includeclassPersonpublic:charm_strName20;longm_ID;staticintm_nCount;/静态成员变量,表示已创建对象的数量public:Person(char*,long);/构造函数staticintGetCount();/静态成员函数;,60,C,Person:Person(char*strName,longID)strcpy(m_strName,strName);m_ID=ID;m_nCount+;/对象数目加1intPerson:GetCount()returnm_nCount;/访问静态成员变量,61,C,intPerson:m_nCount=0;/初始化静态成员变量voidmain()Persone1(LiuJun,1101051);coutPerson:m_nCountn;coute1.m_nCountn;coutPerson:GetCount()n;coute1.GetCount()n;,通过对象访问静态成员变量,通过类访问静态成员变量,通过类调用静态成员函数,通过对象调用静态成员函数,62,C,Persone2(WangXiaogang,1101058);coutPerson:GetCount()n;coute2.GetCount()n;coute1.GetCount()n;,程序运行结果为:1111222,63,C,例静态成员变量和静态成员函数的使用(续),classPersonprivate:charm_strName20;longm_ID;staticintm_nCount;public:Person(char*,long);/构造函数staticintGetCount();/静态成员函数longGetID()returnm_ID;,普通成员函数的定义与实现,如果想用一个静态函数返回m_ID的值,该怎么实现?直接加static可以吗?,64,C,例静态成员变量和静态成员函数的使用(续),classPersonprivate:charm_strName20;longm_ID;staticintm_nCount;public:Person(char*,long);/构造函数staticintGetCount();/静态成员函数staticlongGetID()returnm_ID;,静态成员函数属于类,不属于哪个具体的对象,那么这里的m_ID到底是谁的呢?,直接在普通成员函数前加static,65,C,例静态成员变量和静态成员函数的使用(续),classPersonprivate:charm_strName20;longm_ID;staticintm_nCount;public:Person(char*,long);/构造函数staticintGetCount();/静态成员函数staticlongGetID(Personx)returnx.m_ID;,静态成员函数的定义与实现,66,C,intPerson:m_nCount=0;/初始化静态成员变量voidmain()Persone1(LiuJun,1101051);coutPerson:GetID(e1)n;coute1.GetID(e1)n;Persone2(WangXiaogang,1101058);coutPerson:GetID(e2)n;coute2.GetID(e2)e1.GetID(e1)n;coute2.GetID(e1)e1.GetID(e2)minute=minute;this-second=second;voidCTimeClass:showTime()couthour:minute:secondendl;,74,C,this指针,this指针是一个特殊的隐藏在对象中的指针,每一个处于生存期的对象都有一个this指针,用于指向对象本身。当类的某个非静态成员函数被调用时,系统通过this指针确定是哪一个对象的该成员函数被调用。实际上,this指针总是作为一个隐含参数传递给类的每一个成员函数。,75,C,this指针,一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果。this作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。即使你没有写上this指针,编译器在编译的时候也是加上this的,它作为非静态成员函数的隐含形参,对各成员的访问均通过this进行。例如,调用date.SetMonth(9)SetMonth(,编译器会把this指针作为成员函数的参数:,voidTime:showTime(Time*this);couthourminutesecondn=n(不能写成n=n)。,79,C,例this指针的使

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论