第10讲-类与对象-1解析课件

上传人:沈*** 文档编号:241967817 上传时间:2024-08-08 格式:PPT 页数:51 大小:396KB
返回 下载 相关 举报
第10讲-类与对象-1解析课件_第1页
第1页 / 共51页
第10讲-类与对象-1解析课件_第2页
第2页 / 共51页
第10讲-类与对象-1解析课件_第3页
第3页 / 共51页
点击查看更多>>
资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,2008,年,02,月 张华 武汉大学,第十讲 类与对象,第十讲 类与对象,类和对象的概念,类的定义,对象,对象的定义,引用对象的成员,对象的赋值,对象的作用范围和生存期,构造函数,析构函数,C+,语言程序设计,2,概述,类和对象,类和对象是面向对象程序设计(,OOP,)的两个最基本概念。,对象就是客观事物在计算机中的抽象描述。,是问题域中的实体。,例如绘画程序中的一个矩形,游戏程序中的一个具体人物。,类是对具有相似属性和行为的一组对象的统一描述。,例如绘画程序中的形体,游戏程序中的一类角色。,类与对象,3,类,C+,的类是在结构体的基础上扩充而来的。,类是把各种不同类型的数据(称为数据成员)和对数据的操作(成员函数)组织在一起而形成的用户自定义的数据类型。,C,语言中的结构体只包含具有某种联系的不同类型的数据成员。,C+,中,类定义包括类说明和类实现两大部分。,说明部分提供了对该类所有数据成员和成员函数的描述。,实现部分提供了所有成员函数的实现代码。,类与对象,4,类,定义类的一般形式,使用,class,的格式,类与对象,class,类名,private,:,私有的,数据成员或成员函数,protected,:,保户的,数据成员或成员函数,public,:,公有的,数据成员或成员函数,;,各成员函数的实现代码,5,类,定义类的说明,class,是定义类的关键字,类名由用户自己定义,必须是,C+,的有效标识符,一般首字母大写。,大括号括起来的部分是类的成员(数据成员和函数成员)。,它们分成三部分,分别由,private,、,public,、,proctected,三个关键字后跟冒号来指定。,这三部分可以以任何顺序出现,且在一个类的定义中,这三部分并非必须同时出现。,类与对象,6,类,定义类的说明,类的成员,private,成员,在类之外是不能存取的,只有类中的成员函数才能存取,private,的数据成员和成员函数。,protected,成员,只有类的成员函数及其子类(派生类)可以存取,protected,的成员。,public,成员,可,被程序中的任何函数或语句存取,,public,成员多为成员函数,用来提供一个与外界的接口,外界只有通过这个接口才可以实现对,private,成员的存取,。,当定义类时,当未指明成员是哪部分时,默认是属于,private,成员,但一般不要采用默认形式,。,类与对象,7,类,定义类的说明,例如:,描述图书的类的定义,类与对象,class,Book,private:,char name20;,/,表示图书的名称,int,number;,/,表示图书编号,public:,void,regist(char,*,a,int,b);/,给各数据成员赋值,void show();,/,显示各数据成员的值,;,8,类,定义类的说明,使用,struct,定义类,例如:描述图书的类的定义,与用,class,定义的唯一区别:,当未指明,成员访问属性时,,默认,是,public,成员,。,类与对象,struct,Book,private:,char name20;,/,表示图书的名称,int,number;,/,表示图书编号,public:,void,regist(char,*,a,int,b);/,给各数据成员赋值,void show();,/,显示各数据成员的值,;,9,类,定义类的说明,要特别注意,在类的定义中,类的说明部分的右边大括号后面必须有一分号。,根据类的定义,可看出:,类是实现封装的工具。,所谓,封装,就是将类的成员按使用或存取的方式分类,有条件地限制对类成员的使用。,封装是通过public和private访问属性与成员函数实现的。,private的成员构成类的内部状态。,public的成员则构成与外界通信的接口。,通过public的成员函数来使用private的数据成员,从而在C+中实现了封装。,类与对象,10,类,成员函数的定义,类中的成员函数可以在以下两处定义:,将成员函数的定义直接写在类的定义中。,在类的定义体中只写出成员函数的原型说明,而成员函数的定义写在类的定义之后。,将成员函数的定义直接写在类中,如:对于前面定义的图书类Book来说,其成员函数regist和show的定义可直接写在类的定义体中。,类与对象,11,类,成员函数的定义,将成员函数的定义直接写在类中,(cw1001),类与对象,class Book,private:,char name20;,int,number;,public:,void,regist(char,*,a,int,b),/,成员函数,regist,(),的定义,strcpy(name,a,);/,给数据成员,name,赋值,number=b;/,给数据成员,number,赋值,void show(),/,成员函数,show(),的定义,cout,名称:,name,endl,;,cout,号码:,number,endl,;,;,在类中直接定义成员函数的情况一般适合于成员函数规模较小的情况,也就是说它们一般为内联函数,即使没有明确用,inline,关键字。,12,类,成员函数的定义,在类的定义体中只写出成员函数的原型说明,而成员函数的定义写在类的定义之后。,这种情况比较适合于成员函数体较大的情况。,这时要求在定义成员函数时,在函数的名称之前加上其所属类名及作用域运算符“:”。,定义成员函数的一般类型为:,返回值类型 类名,:,成员函数名(参数表),函数体,类与对象,13,类,成员函数的定义,将成员函数的定义写在类定义的外面,(,cw1002,),类与对象,#include,#include,class Book,private:,char name20;,int,number;,public:,void,regist(char,*,a,int,b);/,成员函数,regist,(),的声明,void show();/,成员函数,show(),的声明,;,14,类,成员函数的定义,将成员函数的定义写在类定义的外面,(cw1002),续,类与对象,void,Book:regist,(char,*,a,int,b)/,成员函数,regist,(),的定义,strcpy(name,a,);/,给数据成员,name,赋值,number=b;/,给数据成员,number,赋值,void,Book:show,()/,成员函数,show(),的定义,cout,名称:,name,endl,;,cout,号码:,number”,。,类与对象,19,对象,访问对象的成员,注意:,任何对对象私有数据的访问都必须通过向对象发送消息来实现,而且所发送的消息还必须是该对象能够识别和接受的。,在,C+,中,消息发送正是通过公有成员函数的调用来实现的。,由于类接口隐藏了对象的内部细节,用户只能通过类接口访问对象,因此,在类设计中必须提供足够的公有接口以捕获对象的全部行为,这正是类设计中的一个最基本的要求。,类与对象,20,对象,this,指针,成员函数如何知道某次调用的对象?,在对象调用,book1.regist(“C+,编程教程”,1001);,时,成员函数,regist,除了接受两个实参外,还接受了一个对象,book1,的地址,这个地址被一个隐含的形参,this,指针所获取,它等同于执行,this=&book1,,那么所有对数据成员的访问都隐含地被加上前缀:,this-,。,因此,在成员函数体,regist,中,执行,就等价于,类与对象,strcpy(name,a,);,number=b;,strcpy(this,-,name,a,);,this-number=b;,21,对象,this,指针,成员函数如何知道某次调用的对象?,这样,上例中的成员函数,regist,也可这样定义:,通过以上方法就确保了不同对象调用成员函数时访问的是不同对象的数据,而它们之间没有干扰。,类与对象,void,Book:regist(char,*,a,int,b),strcpy(this,-,name,a,);,this-number=b;,22,对象,对象赋值语句,对于同一个类生成的两个对象,可以进行赋值,其功能是将一个对象的数据成员赋值到另一个对象中去。,例如,类与对象,#include,Book.h,void main(),Book book1,book2;,book1.regist(C+,语言程序设计,1001);,book2=book1;,book1.show();,book2.show();,名称:,C+,语言程序设计,号码:,1001,名称:,C+,语言程序设计,号码:,1001,23,对象,对象的作用域与生存期,对象是类的实例,它实质就是某种数据类型的变量,在不同的位置以不同的方式定义对象时,其作用域和生存期是不同的。,局部对象(不包括局部静态对象),其作用域是定义它的函数体,生存期从函数调用开始到函数调用结束,下一次再重新调用函数时,再重新构造对象。,构造局部对象的次序(即分配存储单元)是按它们在函数体中声明的顺序。,全局对象,全局对象的作用域是整个程序,生存期是整个程序的运行时间。它也是在程序运行前(即在主函数运行前)只构造一次。,类与对象,24,对象,对象的作用域与生存期,静态对象(局部静态和全局静态),其作用域是定义它的函数体或程序文件,其生存期是整个程序。构造静态对象的次序是按它们在程序中出现的先后次序,并在整个程序运行开始时(即在主函数运行前)只构造一次。,类中成员的构造次序是以类中声明成员的次序进行。,类与对象,25,对象的初值,变量的初值,全局变量和静态变量在定义时,将自动赋初值为,0,;局部变量在定义时,其初始值不固定的。,对象的初值,当对象被定义时,由于对象的意义表达了现实世界的实体,所以一旦定义对象,就必须有一个有意义的初始值。,与变量定义相似,如果创建的是全局对象或静态对象,则对象的默认值为,0,,否则对象的初始值是不定的。,指对象的数据成员的初值。,类与对象,26,对象的初值,案例分析:对象的初值,观察全局对象或静态对象,局部对象的初始值。,类与对象,#include,class Person,private:,char name20;,int,age;,public:,void show(),cout,Name:name|age:age,endl,;,person1,;,Name:|age:0,Name:,烫烫烫烫烫烫烫烫烫烫烫烫,?|age:-858993460,void main(),person1.show();,Person,person2,;,person2.show();,27,对象的初始化,变量的初始化,变量在定义时通过初始化式指定初值。,对象的初始化,在,C+,中,在定义对象的同时,给该对象初始化的方法就是利用构造函数。,只包含数据成员的结构体类型的变量可以采用初始化式。,类与对象,struct,Date,int,year,month,day;,today=2008,2,10;,28,构造函数,构造函数,(,constructor,),构造函数是与类名同名的特殊的成员函数,当定义该类的对象时,构造函数将被自动调用以实现对该对象的初始化。,构造函数的定义格式为:,类名,(,形参说明,),函数体,构造函数不能有返回值,因而不能指定包括,void,在内的任何返回值类型。,构造函数的定义体可与其它函数成员一样,放在类内或类外都可。,构造函数既可定义成有参函数,也可定义成无参函数,要根据问题的需要来定。,类与对象,29,构造函数,案例分析:构造函数,类,Person,包括,4,个数据成员,用来记录人员信息。生成对象,obj,,并使用构造函数为,obj,赋予初始值。,(,cw1005,),类与对象,#include,#include,class Person,private:,char name10;,int,age;,int,salary;,char tel8;,public:,Person(char,*,xname,int,xage,int,xsalary,char*,xtel,);,void,disp,();,;,30,构造函数,案例分析:构造函数,类与对象,Person:Person(char,*,xname,int,xage,int,xsalary,char*,xtel,),strcpy(name,xname,);,age=,xage,;,salary=,xsalary,;,strcpy(tel,xtel,);,void,Person:disp,(),cout,endl,;,cout,姓名:,name,endl,;,cout,年龄:,age,endl,;,cout,工资:,salary,endl,;,cout,电话:,tel,endl,endl,;,31,构造函数,案例分析:构造函数,类与对象,void main(),Person,obj,(,张立三,25,850,45672314),;,obj.disp,();,姓名:张立三,年龄:,25,工资:,850,电话:,45672314,32,构造函数,构造函数的重载,如果一个类中出现了两个以上的同名的成员函数时,称为类的成员函数的重载。,案例分析:重载的构造函数,类,Book,定义两个重载的构造函数,其中一个是无参函数,另一个是有参函数。,(,cw1006,),类与对象,class Book,private:,char bookname30;,int,number;,public:,Book();,/,第,1,个构造函数说明,Book(char,*a,int,b);,/,第,2,个构造函数说明,void show();,;,33,构造函数,案例分析:重载的构造函数,类与对象,Book:Book,()/,第,1,个构造函数定义,strcpy(bookname,“no name);,number=0;,Book:Book(char,*a,int,b)/,第,2,个构造函数定义,strcpy(bookname,a);,number=b;,void,Book:show,()/show,的函数定义,cout,bookname,is:,bookname,endl,;,cout,booknumber,is:number,endl,;,34,构造函数,案例分析:重载的构造函数,类与对象,void main()/,主程序,/,自动调用构造函数Book(char,*,a,int,b),Book,mybook(Visual,C+6.0,10020),;,mybook.show,();,/,自动调用构造函数Book,(),Book,yourbook,;,yourbook.show,();,bookname,is:Visual C+6.0,booknumber,is:10020,bookname,is:no name,booknumber,is:0,可见,当出现构造函数重载时,其匹配方式同普通函数重载时的匹配方式。,35,构造函数,默认构造函数,C+,规定,每个类必须有一个构造函数。,如果在类中没有显式定义构造函数时,则,C+,编译系统在编译时为该类提供一个,默认的构造函数,,该默认构造函数是个无参函数,它仅负责创建对象,而不做任何初始化工作。,在用默认构造函数创建对象时,如果创建的是全局对象或静态对象,则对象的默认值为,0,,否则对象的初始值是不定的。,只要一个类定义了一个构造函数(不一定是无参构造函数),,C+,编译系统就不再提供默认的构造函数。,类与对象,36,构造函数,带缺省参数的构造函数,当构造函数有缺省参数时,称为具有缺省参数的构造函数,在使用时要防止二义性。,类与对象,class,Myclass,private:,int,member;,public:,Myclass,();,Myclass(int,i);,;,Myclass:,Myclass,(),member=10;,Myclass:,Myclass(int,i=10),member=i;,void main(),Myclass,x(20);,/,下面一行产生二义性,,,/,无法确定自动调用哪个构造函数完成对象的构造,Myclass,y;,ambiguous call to overloaded function,37,析构函数,析构函数,当一个对象被定义时,系统自动调用构造函数为该对象分配相应的资源,当对象使用完毕后,这些系统资源需要在对象消失前被释放。,析构函数是类的一个特殊成员函数,其函数名称是在类名的前面加上,它没有返回值,没有参数。,不能被随意调用,只是,在对象生命期结束时,被系统自动调用,。,析构函数的定义方式为:,类名(),函数体,类与对象,38,析构函数,析构函数,一个类中,只能拥有一个析构函数,,即不能重载。,如果程序员在定义类时,没有为类提供析构函数,则系统会自动创建一个,默认的析构函数,,其形式为:,类名,(),对于一个简单的类来说,大多可以直接使用系统提供的默认析构函数。但是,如果在类的对象中有动态分配的内存(如:用new申请分配的内存)时,就必须为该类提供适当的析构函数,完成清理工作(释放内存)。,对象被析构的顺序与对象建立时的顺序正好相反。,即最后构造的对象先被析构。,类与对象,39,析构函数,案例分析:析构函数,类Teacher的构造函数为name申请存储空间,在析构函数中释放该空间。,(cw1008),类与对象,#include,#include,class Teacher,private:,char*name;,int,age;,public:,Teacher(char,*i,int,a),/,用new为name成员分配堆内存,name=new charstrlen(i)+1;,40,析构函数,案例分析:析构函数,类与对象,strcpy(name,i);,age=a;,cout,执行构造函数Teacher,(),endl,;,;,Teacher(),delete name;,cout,执行析构函数Teacher,(),endl,;,;,void show();,;,void,Teacher:show,(),cout,姓名,:name,endl,年龄,:age,endl,;,41,析构函数,案例分析:析构函数,类与对象,void main(),Teacher,teacher,(张立三,25);,teacher,.show,();,cout,endl,;,执行构造函数,Teacher(),姓名:张立三,年龄:,25,执行析构函数,Teacher(),什么时候被执行的?,42,拷贝构造函数,拷贝构造函数,拷贝构造函数是C+中引入的一种新的构造函数。,定义一个拷贝构造函数的方式是:,类名(const 类名&形式参数),函数体,由此可看出:,拷贝构造函数的名称与类的名称相同,且它只有一个参数,该参数就是对一个该类对象的引用。,拷贝构造函数的功能是,用于实现对象值的拷贝,,通过将一个同类对象的值拷贝给一个新对象,来,完成对新对象的初始化,,即用一个对象去构造另外一个对象。,初始化式,参数传递,类与对象,43,拷贝构造函数,案例分析:,拷贝构造函数,(cw1009a),类与对象,class Point,private:,int,x,y;,public:,Point,(),Point(int,inx,int,iny,),x=,inx,;,y=,iny,;,Point(Point,&p),x=,p.x,;,y=,p.y,;,cout,执行拷贝构造函数,endl,;,void,Show(char,*name),cout,endl,name,(x,y),endl,;,;,void,Print(Point,p),p.Show,();,44,拷贝构造函数,案例分析:拷贝构造函数,类与对象,void main(),Point p1(1,2),p2;,p2=p1;,cout,执行对象间的赋值,endl,;,Point p3(p1);,p1.Show(p1);,p2.Show(p2);,p3.Show(p3);,Point p4=p1;,cout,endl,p4;,Print(p4);,45,拷贝构造函数,默认的拷贝构造函数,如果程序员没有为所设计的类提供显式的拷贝构造函数,则系统会自动提供一个,默认的拷贝构造函数,。,其功能是:把作为参数的对象的数据成员逐个拷贝到目标变量中,这称为成员级复制(或,浅拷贝,)。,类与对象,46,拷贝构造函数,案例分析:,浅拷贝的问题。,(cw1009b),类与对象,class Person,private:,char*name;,int,num;,public:,Person(int,i,char*,str,),name=new charstrlen(str)+1;,strcpy(name,str,);,num=i;,47,拷贝构造函数,案例分析:,浅拷贝的问题。,(cw1009b),类与对象,void list(),cout,name=name,endl,;,cout,num =num,endl,;,void,SetName(char,*,str,),strcpy(name,str,);,;,48,拷贝构造函数,案例分析:浅拷贝的问题,类与对象,void main(),/,调用函数Person(int,i,char,*,str,)构造person1,Person person1(215,张立三,);,cout,Person 1:,endl,;,person1.list();,/使用拷贝构造函数构造person2,Person person2(person1);,cout,Person 2:,endl,;,person2.list();,/更新person1的name成员的值,person1.SetName(李大勇);,cout,Person 1:,endl,;,person1.list();,/同时更新了person2的name成员的值,cout,Person 2:,endl,;,person2.list();,49,拷贝构造函数,案例分析:,浅拷贝和深拷贝,类与对象,堆空间,对象,A,对象,B,堆空间,对象,A,对象,B,堆空间,浅拷贝,深拷贝,50,拷贝构造函数,案例分析:通过拷贝构造函数实现深拷贝,类与对象,class Person,public:,Person(const,Person&x),name=new charstrlen(x.name)+1;,strcpy(name,x.name,);,num=,x.num,;,51,
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


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


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

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


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