




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
技能基础培训四C++面向对象程序设计Page*****目录静态成员类成员指针this指针子对象堆对象常对象函数模板类模板Page*****类静态成员静态成员分为:静态数据成员和静态成员函数静态数据成员 静态数据成员是类的所有对象共享的成员,而不是某个对象的成员。使用静态数据成员可以节省内存,因为它是所有对象所共有的,只需存储一处,供所有对象共用。静态数据成员的值对每个对象都是一样的,但是它的值是可以更新的。Page*****静态数据成员定义方法1,在一般数据成员前加关键字static2,静态数据成员初始化与一般数据成员初始化不同。其初始化如下: 数据类型类名::静态数据成员名=值;这说明:初始化在类体外进行,而前面不加static,以免与一般静态变量或对象相混淆。初始化时不加该成员的访问权限控制符private,public等初始化时使用作用域来表明它所属的类静态成员必须进行初始化。引用静态数据成员时,既可以通过对象引用,也可以采用如下格式:类名::静态数据成员名Page*****示例程序classA{ staticinta;};voidmain三{ cout<<sizeof(A)<<endl; }classA{ inta;};voidmain三{ cout<<sizeof(A)<<endl; }前者执行结果是1,后者是4.从而可见静态数据成员节省内存空间Page*****静态成员函数静态成员函数是类的静态成员,而不是对象成员。定义方式是在普通成员函数前加static调用静态成员函数时既可以通过对象来调用,也可以通过类来调用。在静态成员函数的实现中,不能直接引用类中说明的非静态成员,但是可以引用类中说明的静态数据成员。如果静态成员函数中要引用非静态成员时,则可通过对象来调用。Page*****示例程序classSl{ private: intn;staticintm;public: Sle(inti){ n=i; m+=i;}Staticvoiddisp(Slec){ cout<<“n=”<<c.n<<“,m=”<<m<<endl;}};Page*****示例程序intSle::m=2;voidmain三{ SleA(2),B(4); A.disp(B);//通过对象A调用静态成员函数 Sle::disp(A);//通过类调用静态成员函数}该程序的执行结果如下:n=4,m=8n=2,m=8Page*****类成员指针类成员指针包括类数据成员指针和类成员函数指针类数据成员指针一般定义格式如下:类型类名::数据成员指针名由于类不是运行时存在的对象,因此,使用类数据成员指针时,需要首先指定类的一个数据成员,然后通过类的对象来引用指针所指向的成员。Page*****示例程序(类数据成员指针)classSle{public: voiddisp三{ cout<<“m=”<<m<<endl; cout<<“n=”<<n<<endl;}intm,n;//公有数据成员};voidmain三{ intSle::*p=&Sle::m; Slea; a.*p=10;//等价于a.m=10}Page*****类成员函数指针指向类成员函数的指针定义格式如下:类型(类名::*成员函数指针名)(参数表)给类成员函数指针赋值的格式如下:指向成员函数的指针名=函数名程序中使用指向函数的指针调用函数的格式如下:(*指向函数的指针名)(实参表)Page*****示例程序classSl{ private: intn,m;public: voidsetm(inti){n=i;}voidsetn(inti){n=i;}voiddisp三{ cout<<“n=”<<n<<“,m=”<<m<<endl;}};voidmain三{ void(Sle::*pfub)(int); Slea; pfun=Sle::setm; (a.*pfun)(10); //等价于a.setm(10);}Page*****this指针在设计好一个类后,通过定义类对象来调用类的成员函数,其使用格式为: 对象.成员函数在C++中,每个当前对象都隐含一个指向该对象的指针,即this指针。显然,this指针的类型就是成员函数所属的类的类型
Page*****示例程序classSl{ private: intn;public:Sle(intm){n=m;}voidaddvalue(intm){ Sles; s.n=n+m; *this=s;}voiddisp三{ cout<<“n=”<<n<<endl;}};voidmain三{ Sles(10); s.disp三; s.addvalue(5); s.disp三; }Page*****示例程序进行说明本程序执行的结果是n=10,n=15上述程序中,Sle类中定义了一个addvalue非静态成员函数,语句s.addvalue(5);通过对象s来调用addvalue三成员函数,其中隐含一个指向对象s的指针,该语句告诉系统是将s对象的私有数据成员n增大5,而不是其他对象。它实际上相当于以下函数调用:addvalue(&s,5);即将类对象的地址作为第一个参数传递给了函数。addvalue函数的原型实际是:voidaddvlue(Sle*this,intm)。该函数的第一个参数指向该类对象的一个指针,即this指针。我们定义该成员函数时,并没有看到这样一个参数,因为这个参数是系统隐含的。在成员函数的定义体中,可以通过this访问这一参数。Page*****this指针this指针只能在类的成员函数中使用,它指向该成员函数被调用的对象。示例程序classSle{ intn;public: Sleadd(Sles1,Sles2){ this->n=s1.n+s2.n;return(*this);}};Page*****this指针Attention:静态成员函数没有this指针。因为类只有一个静态成员函数实例,所以使用this指针没有什么意义。在静态成员函数中使用this指针会引起编译错误,不然静态成员函数就会像非静态成员函数一样使用指针进行访问了。Page*****子对象当一个类的数据成员是另一个类的对象时,这个对象就称为子对象。子对象可以像通过对象那样使用,唯一要考虑的是:子对象构造函数和析构函数的执行次序。一般的,设类A含有子对象obj,该子对象对应的类是B,如:classB{};classA{Bobj;//obj是类B的对象,是类A的子对象。。};为了调用子对象obj的构造函数,设计类A的构造函数如下:A(参数表):obj(参数表2){函数体;}Page*****说明当建立obj调用类B的不带参数的构造函数时,可省略obj讲义 当类A中有多个字对象时,在A构造函数”:“后列出各子对象的初始化表达式,它们之间用逗号分隔,称为子对象初始化列表。A构造函数的执行次序是,以子对象在类A中说明的顺序调用子对象初始化列表中列出的各构造函数,然后执行函数体。Page*****示例程序classB{ intb;public: B三{b=1;} voidprintb三{cout<<"b="<<b<<endl;}};classA{ inta; Bc;public: A(inti){a=i;}; voidprinta三 { cout<<"a="<<a<<endl; c.printb三; }};voidmain三{ Aa(2); a.printa三;}Page*****说明该程序中,类A有一个子对象c,它是类B的对象。由于建立c子对象调用类B的不带参数的构造函数,所以类A构造函数没有给出c三.对于Aa(2)语句,执行类A的构造函数,其过程是:先调用B类构造函数,给c.b赋值1,再执行a=2.本程序执行结构是a=2b=1Page*****析构函数在含有子对象的类A中,设计析构函数如下:~A讲义 {函数体;};其执行次序是:先执行函数体,再以子对象在类A中说明的相反次序调用各类的析构函数Page*****示例程序classB1{public: B1三{cout<<"B1:Constructor"<<endl;} ~B1三{cout<<"B1:Descontructor"<<endl;}};classB2{public: B2三{cout<<"B2:Constructor"<<endl;} ~B2三{cout<<"B2:Descontructor"<<endl;}};classB3{public: B3三{cout<<"B3:Constructor"<<endl;} ~B3三{cout<<"B3:Descontructor"<<endl;}};classA{ B1b1; B2b2; B3b3;public: A三:b3三,b2三,b1三{cout<<"A"<<endl;} ~A三{cout<<"A:Descontructor"<<endl;}};voidmain三{ Aa;}Page*****程序分析程序中定义了四个类,类A中含有3个子对象b1,b2,b3,分别是类B1,B2,B3的对象,其说明次序是b1,b2,b3,按照子对象构造函数和析构函数的执行次序得到以下的程序运行结果B1:ConstructorB2:ConstructorB3:ConstructorA:ConstructorA:DestructorB1:DestructorB2:DestructorB3:DestructorPage*****堆对象所谓堆对象是指在程序运行过程中根据需要随时建立或删除的对象。这种堆对象被创建在内存一些空闲的存储单元中,这些存储单元称为堆。它们可以被创建的堆对象占有,也可以通过删除堆对象而获得释放。创建或删除堆对象时,需要如下两个运算符:new或delete这两个运算符又称为动态分配内存空间运算符。new相当于C语言的malloc讲义 函数,delete相当于C语言的free讲义 函数Page*****运算符new的用法运算符new的用法该运算符的功能是用来创建堆对象,或者说,它是用来动态地创建对象。new运算符使用格式如下:new类型说明符(初始化列表)它说明在堆中建立一个由"类型说明符"给定的类型的对象时,并且由括号中的"初始值列表"给出被创建对象的初始值.如果省去括号和括号中的初始值,则被创建的对象选用默认值.使用new运算符创建对象时,可以根据其参数来选择适当的构造函数,不需要sizeof来计算对象所占用的字节数,便可以计算其大小.new运算符返回一个指针,指针类型将与new所分配对象相匹配,如果不匹配要通过强制类型转换,否则将出现编译错误.如果new运算符不能分配到所需要的内存,它将返回0,这时的指针为空指针.new运算符也可以来创建数组类型的对象,即对象数组,其格式如下:new类名[算术表达式]Page*****其中,"算术表达式"的值为所创建的对象数组的大小.例如:A*ptr;ptr=newA[5];其中,A是一个已知的类名,ptr指向类A对象的一个指针.通过newA[5]创建一个对象数组,该数组有5个元素.它的返回值赋给指针ptr,于是ptr便指向对象数组的指针.使用new[]创建对象数组或一般数组时,不能为该数组指定初始值,其初始值为默认值.注意:(1)用new创建对象时,要调用构造函数.(2)使用new[]来创建对象数组时,类中必须说明默认默认构造函数(3)使用new创建类sle的对象数组Sle[n]时,系统调用默认构造函数n次.Page*****运算符delete的用法该运算符的功能是用来删除使用new创建的对象或一般类型的指针.其格式如下:delete<指针名>例如:A*ptr;ptr=newA(5,6);deleteptr;其中,ptr是一个指向类A的指针,使用new给ptr分配了内存空间,又使用了delete删除了指针ptr.运算符delete也可以用来删除使用new创建的对象数组,其使用格式如下:delete[]指针名例如:A*ptr;ptr=newA[5];delete[]ptr;其中,ptr指向类A对象的指针.它被赋值为指向一个具有5个元素的类A的对象数组的首元素.使用delete删除了这个数组.Page*****运算符delete的用法注意:(1)运算符delete必须使用于由运算符new返回的指针.(2)该运算符也适用于空指针(即其值为0的指针)(3)对一个指针只能使用一次delete操作(4)指针名前只用一对括号符,并且不管所删除数组的维数,忽略方括号内的任何数字.(5)用delete删除对象时,要调用析构函数(6)使用delete删除对象数组时,该数组由多少元素,就调用析构函数多少次.Page*****常类型常类型是指用类型修饰符const修饰说明的类型,常类型的变量或对象的值是不能更新的,所以能够达到既保证数据共享,又防止改变数据的目的.常对象常对象是指对象常量,定义格式如下:类名const对象名或者const类名对象名在定义常对象时必须进行初始化,而且该对象不能再被更新.Page*****常类型例如,有以下程序:classSle{ intn;public: Sle(inti){n=i;} voidsetvalue(inti){n=i;} voiddisplay三{cout<<"n="<<endl;}};voidmain三{ constSlea(10); a.setvalue(6); a.display三;}Page*****常类型本程序中有两个错误,第一个错误是a.setvalue(6);语句,错误信息是"errorC2662:'setvalue':cannotconvert'this'pointerfrom'constclassSle'to'classSle&'",即常对象不能被更新(setvalue成员函数修改数据成员).第二个错误是a.display三语句,错误信息是"errorC2662:'display':cannotconvert'this'pointerfrom'constclassSle'to'classSle&'",该错误也是由于常对象a不能被更新,尽管dislay三没有修改常对象a.Page*****常对象成员常成员函数使用const关键字说明的函数称为常成员函数,常成员函数的说明格式如下:数据类型函数名(参数表)const注意:(1)const是函数类型的一个组成部分,因此在实现部分也要带const关键字。(2)常成员函数不更新对象的数据成员,也不能调用该类没有用const修饰的成员函数。(3)如果将一个对象说明为常对象,则通过该常对象只能调用它的常成员函数,而不能调用其他成员函数。(4)const可以被用于参与对重载函数的区分。例如类中有如下说明:Voidprint讲义 Voidprint讲义 constPage*****示例程序classSle{ intn;public: Sle(inti){n=i;} voidprint三{cout<<"1:n="<<n<<endl;} voidprint三const{cout<<"2:n="<<n<<endl;}};voidmain三{ Slea(10); constSleb(20); a.print三; b.print三;}Page*****程序说明本程序的执行结果是1:n=102:n=20本程序中Sle类中说明了两个同名函数print,其中一个是常函数,在主函数中说明了两个对象a和b,其中对象b是常对象,通过对象a调用的是没有co
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 分体户合作合同范本
- 分包信贷装修合同范本
- 个人批发合同范本
- 低值易耗品售卖合同范本
- 卫浴建材采购合同范例
- 中外来料加工合同
- 个人简历教师自我评价
- 个人笔迹鉴定申请书
- 原纸代购合同范例
- 个人跟酒店合同范本
- 《研学旅行课程设计》课件-1研学课程资源选择
- 《医学心理学》教案
- 海绵城市建设技术标准 DG-TJ08-2298-2019
- 2024年2天津理工大学马克思主义基本原理概论(期末考试题+答案)
- 跟着名著《小王子》学高考英语读后续写绝佳的续写清单-高中英语作文复习专项
- 产教融合大学科技园建设项目实施方案
- 交通法律与交通事故处理培训课程与法律解析
- 广西版四年级下册美术教案
- 《换热器及换热原理》课件
- 儿童权利公约演示文稿课件
- UPVC排水管技术标准
评论
0/150
提交评论