类和对象及其封装性.ppt
《类和对象及其封装性.ppt》由会员分享,可在线阅读,更多相关《类和对象及其封装性.ppt(143页珍藏版)》请在三一办公上搜索。
1、第三章 类和对象及其封装性,本章要点1 类的定义及其类对象的封装性2 类成员函数的定义3 类对象的定义和使用4 类的构造函数和析构函数5 类对象的动态创建和释放6 类对象的赋值与复制7 与类对象有关的指针8 类的静态成员9 类对象成员、类对象数组和类对象参数10 友元(友元函数、友元成员和友元类)11 类的只读成员函数定义,3.1 类的定义及其类对象的封装性 无论采用哪种程序设计范型所设计的程序都是由数据处理这些数据的操作组成的。程序的运行就是按照特定的结构和流程将操作施加在相应的数据上,完成程序需要实现的功能。在传统设计范型中,数据是使用语言所提供的简单数据类型和构造数据类型(例如 C 语言
2、中的结构类型 struct)定义生成的;而操作是通过过程或函数的形式定义提供的。,在面向对象设计范型中,使用了数据抽象的概念,即数据总是与允许施加它们的操作绑定在一起的。这就要求编程语言能够提供符合数据抽象的预定义数据类型,特别需要提供能构造符合数据抽象用户自定义类型的构造数据类型(例如 C+和 Java 语言中的类类型 class)。程序中的数据和操作都是由按数据抽象封装起来的对象提供的。,3.1.1 C+的类类型定义 在 C+中,用户可以使用类类型关键字 class 定义自己的抽象数据类型。这种定义方法和形式与使用结构体类型关键字 struct 定义数据结构类型十分相似。例如,可以用 st
3、ruct 定义描述学生基本信息的数据结构类型 Student:struct Student int num;char name20;char sex;,同样,可以用 class 定义描述学生基本信息和基本操作的数据类型 Student:class Student int num;char name20;char sex;public:void display()cout“num:”num endl;cout“name:”name endl;cout“sex:”sex endl;,比较两种用户自定义类型,它们的共同之处表现在:类型定义首行的格式相同,由类型关键字(struct 或 class)与
4、自定义类名组成。例如:“struct Student”和“class Student”。类型定义体都使用左花括号“”表示开始,使用右 花括号“”表示结束,并用分号“;”表示整个自定义 类型定义工作完成。使用自定义类型(结构或类)定义类型实体(结构 变量或类对象)的格式相同。在面向对象的程序设计中通常将所有的类型(包括 系统预定义的简单数据类型)实体可以统一称为对 象。例如,可使用自定义结构类型 Student 定义结构 对象:Student stud1,stud2;也可使用自定义类类型 Student 定义类对象:Student stud1,stud2;,在面向对象的程序设计中通常将所有的类型
5、(包括 系统预定义的简单数据类型)实体可以统一称为对 象。例如,可使用自定义结构类型 Student 定义结构 对象:Student stud1,stud2;也可使用自定义类类型 Student 定义类对象:Student stud1,stud2;,二者的不同之处表现在:使用 C 语言的 struct 定义的结构类型的定义体中只 包含数据成员,而使用 class 定义类类型的定义体中 既包含数据成员,还包含了操作这些数据的成员函 数。注意,在 C+中,struct 定义能力被扩展,也可 以 class 定义一样包含操作数据成员的成员函数。结构类型的成员的缺省访问权限均为公有,即可以 从结构对象
6、外直接访问。例如:Student stud1;cout“num:”stud1.num endl;,cout“name:”stud1.name endl;cout“sex:”stud1.sex endl;而类类型的成员的缺省访问权限均为私有,例如,类 Student 中的数据成员就不能从类外直接访问,而 显示这些数据只能通过调用成员函数 display 实现。Student stud1;cout“name:”stud1.name endl;/非法stud1.display();,3.1.2 类类型成员的访问权限 为了实现类对象的封装性(数据隐藏和提供访问接口)类类型定义为类成员提供了私有和公有两
7、种基本访问权限供用户选择。1 私有成员 访问权限:只限于类成员访问。关键字:private 声明或从定义体开始的缺省声 明。例如,下面的 Student 定义与前面的 Student 定义等价的:,class Studentprivate:int num;char name20;char sex;public:void display()cout“num:”num endl;cout“name:”name endl;cout“sex:”sex endl;,私有段:从 private:开始至其它访问权限声明之间 所有成员组成的代码段。例如 Student 定义中从 private:开始到 pub
8、lic:之间的所数据成员。成员种类:数据成员和成员函数。2 公有成员 访问权限:允许类成员和类外的任何访问。关键字:public。公有段:从 public:至其它成员声明之间所有成员 组成的代码段。成员种类:数据成员和成员函数。,使用私有成员来隐藏由类对象操作的数据,然后提供相应的公有成员函数来访问和操作这些数据,而访问和操作这些数据实现细节通常是被隐藏起来的。除了私有和公有两种基本访问权限外,类类型定义还提供了允许类成员和派生类成员访问,而不允许类外访问的保护成员访问权限(protected),以满足实现继承性的需要。,为了使 C+语言所设计程序中的数据都能实现数据抽象,并能与 C 语言设计
9、的程序中的数据兼容,C+仿照类类型定义的功能,对 struct 定义的结构体类型功能进行如下扩展:定义体中也可以包括对数据成员进行处理和操作的 成员函数。添加了与类类型定义相同的成员访问权限声明功 能,但仍然保留了缺省声明表示成员的访问权限为 公用的基本特点。扩展后的 struct 可以定义与类类型效果相同的结构类型,例如:,struct Studentprivate:int num;char name20;char sex;public:void display()cout“num:”num endl;cout“name:”name endl;cout“sex:”sex endl;,该结构类
10、型与先前使用 class 定义的 Student 类型的效果完全相同。请注意,这并不意味着可以用 struct 替代 class,因为使用 class 定义的类类型的缺省私有性质能更方便、安全地实现面向对象程序设计对类对象的要求,因此强烈建议使用 class 建立数据类型;而只有希望所建立类型的全部成员都是公有访问权限时,使用 struct 建立结构类型比较方便。,3.1.3 类类型的构造 类类型定义为所定义的数据类型建立了一个明确的边界,类定义体中的私有成员(数据成员和成员函数)和公有成员函数的实现细节均被封装在此边界内,使得这些类成员和实现细节无法从类对象外被访问,从而受到保护。同时对类公
11、有成员(数据成员和成员函数)的访问和调用又为类对象之间的通讯提供了接口,使得类对象成为一个既访问安全又操作方便的抽象数据实体。下面以一个简单机器人类为例说明类类型的构造:,确定机器人状态的属性:是位置和面对的方向 改变、访问和显示机器人状态的操作:有定位、转向、前进、显示状态等。class Hominoid int dirction;/机器人的方向point location;/机器人的位置 public:void turnLeft();/向左转90度void turnRight();/向右转90度bool advance();/前进一步point location(point loc);/定
12、位bool facingWall();/判断是否面对墙壁void display();/显示当前位置;,bool advance();/前进一步point location(point loc);/定位bool facingWall();/判断是否面对墙壁void display();/显示当前位置;该定义所建立的机器人类的构造可以形象地用下图表示,它很象一个封装好的器件。,directionlocation,Java 的类定义与 C+的类定义在格式上基本相同,但有两点是不一样的:成员的访问权限必须逐个显式说明;类定义结束不要分号“;”。例如:class User private String
13、 name;private int age;public User(String str int yy)name=str;age=yy;返回,3.2 类成员函数的定义1 成员函数的性质 类的成员函数在声明和定义的格式上以及用法和作 用上与一般函数基本一致。但由于成员函数是属于 某一个类的成员,因此它与一般函数的区别表现:作用域在类定义体所确定的边界内,即可以访问 本类的任何成员(私有和公有的数据和函数)。需要根据功能和作用指定成员函数的访问权限,一般情况下,将向类外提供操作功能的成员函数 指定为 public,将只为类内提供服务功能的成员函 数指定为 private,将只为类内和派生类提供服务
14、 功能的成员函数指定为 protected。,2 成员函数的声明和定义形式 在类定义体内定义成员函数的实现代码。这种形 式下,函数定义的首部将起到函数原型的作用,因此无须成员函数定义之前的原型声明。例如:class point int x,y;public:void setpoint(int vx,int vy)x=vx;y=vy;,在类定义体内声明成员函数,而在类定义体外定 义成员函数的实现代码。采用这种定义形式的 时,类定义体外的定义代码必须满足:在成员函数名之前应缀上所属的类名:,“:”是 作用域运算符,以便说明函数的作用域。成员函数定义的首部(函数的返回类型、函数 名和参数表列)必须与
15、在类定义体中声明的该 函数的原型一致。例如:,class point int x,y;public:void setpoint(int,int);void point:setpoint(int vx,int vy)x=vx;y=vy;由于第 种形式不仅可以减少类定义体的代码长 度,使类定义体清晰、可读性好;更重要的是有助 于类的操作接口与操作实现细节相分离,并隐藏细 节。因此,提倡采用该形式定义类成员函数。,3 类的内置(内联)成员函数定义方式:隐式定义 函数定义在类定义体中,此时只 要函数的实现代码符合内置函数的定义要求,该 成员函数就会自动被定义内置函数,而说明内置 函数的关键字 inli
16、ne 可以忽略。例如:class point int x,y;public:void setpoint(int vx,int vy)/内置函数 x=vx;y=vy;其中成员函数 setpoint 定义的首部与加缀 inline 的 首部“inline void setpoint(int vx,int vy)”等效。,显式定义 函数声明在类定义体中,而函数 定义在类定义体外,此时函数定义的首部必须冠 以关键字 inline 说明此函数是内置的。例如:class pointint x,y;public:inline void setpoint(int,int);/内置函数声明;inline voi
17、d point:setpoint(int vx,int vy)/内置函数定义x=vx;y=vy;,需要特别注意的是:由于调用内置函数需要将内置函数的目标代码复制到它被调用的位置,因此编译器在进行内置函数的调用编译时,必须能获得被调内置函数的目标代码。这就需要在调用内置函数的源代码文件中必须包含被调用内置函数的定义代码的源代码文件。也就是说,如果某个被调用的内置成员函数定义在类定义体中,该类定义体代码被保存在一个头文件中,例如“student.h”,则调用该内置函数的源文件应添加预编译命令#include“student.h”。如果该内置函数定义在类定义体外,代码包含在类实现文件中,例如“stu
18、dent.cpp”,则调用该内置函数的源文件应添加预编译命令#include“student.cpp”。,4 成员函数的存储空间 从类类型的定义不难看出,类的数据成员(对象属 性)中保存的数据值代表了类对象的状态,决定了 该类的不同对象的差别,因此当类对象创建时,每 个类对象都必须独占一份(个数相同、类型相同)数据成员存储空间,用于保存区别于其他对象的状 态;而类的成员函数描述了该类所有对象的统一行 为操作,而操作结果(行为表现)的差异取决于不 同对象的状态,因此,成员函数的运行代码被存储 在与数据成员存储空间不同的代码空间中,被该类 的所有对象共享。,例如:由于语句 Student stud
19、1,stud2,stud3;执行所创 建的 3 个 Student 对象在程序运行空间中占用内存的 大小和位置的状态示意如下:返回,3.3 类对象的定义和使用3.3.1 类与对象的关系 类是一组具有相同属性和行为的对象的抽象,是创 建对象的模板,是用户使用 class 创建的自定义类 型。类一旦创建,其作用可与系统预定义类型(例 如,int、double 等)类比。对象是类的实例,创建类的对象可以与创建预定义 类型的变量(例如,int x;、double d;等)类比。类只是提供了该类对象的创建和使用的方法和规 则,因此类本身不占用内存。创建类对象时将按类 定义提供的方法和规则,在内存中为类对
20、象分配空 间,因此,封装是对类对象而言的。,3.3.2 类对象的定义方法:1 先创建类类型,使用时再定义对象 大多数情况均采用该方法定义类对象。这样创建的 类对象的生存周期取决于创建的位置。例如:class Student;void main()Student Zhang,Li;/创建 Student 局部对象 虽然 C+也允许将上述的类对象定义语句写成:class Student Zhang,Li;(C 风格)但不能体现 C+面 向对象的设计风格,且不方便简洁,所以不提倡。,2 在创建类类型的同时定义对象。使用这种方法定义的类对象的生存周期取决于类类 型的创建位置。例如:class Stud
21、entint num;char name20;char sex;public:void display()cout“num:”num endl;cout“name:”name endl;cout“sex:”sex endl;Zhang,Li;,3 不出现类名,直接定义对象。使用这种方法定义类对象的类类型一般在程序中只 出现和使用一次。例如,创建一个描述人员信息的 类类型 person 中包含了一个联系信息属性成员 touchInfo,该属性是一个由人员的通讯地址、邮政编 码、电话号码、e-mail 等信息和相应的处理操作构 成的类类型对象,而该类类型只在定义 touchInfo 属 性出现和使
22、用一次。此时就可以采用本方法在类类 型 person 中定义 touchInfo 属性:,class personclass/无须类名string Addess;string postCode;string poneNum;string E-mail;public:touchInfo;,3.3.3 类对象的使用 类的使用是通过首先创建类对象,然后引用类对象的公有成员(访问数据成员或调用成员函数)达到对该类的使用。依据类对象的创建方式不同,类的使用形式可以分为三种:1 通过对象名和成员运算符访问对象成员一般形式:对象名.成员名;其中成员名必须是对象名所指明对象的所属类的公有数据成员名或公有成员函
23、数名。例如:,class point int x,y;public:setpoint(int vx,int vy)x=vx;y=vy;void fun()point pt;/创建 point 类对象 ptpt.setpoint(10,10);/给 point 对象 pt 的坐标 x,y 赋值pt.x=50;/错误,不能访问私有成员.代码 pt.setpoint(10,10)实际是 pt.point:setpoint(10,10)的缩写,表明通过对象访问对象名所指示的类成员。,2 通过指向对象的指针访问对象成员一般形式:指针名-成员名;其中成员名必须是指针所指对象的所属类的公有数据成员名或公有成
24、员函数名。例如:class point int x,y;public:setpoint(int vx,int vy)x=vx;y=vy;void fun()point*p=new point;/p 指向动态创建的 point 对象p-setpoint(10,10);/给 p 所指对象的坐标 x,y 赋值.,3 通过对象的引用访问对象成员一般形式:对象引用名.成员名;其中成员名必须是对象引用名所引用对象的所属类的公有数据成员名或公有成员函数名。例如:class point int x,y;public:setpoint(int vx,int vy)x=vx;y=vy;void fun()poin
25、t pt,/给 p 引用的对象的坐标 x,y 赋值.,3.3.4 成员名解析 由于类成员作用域在该类定义体所限定的边界内,因此,不同类中具有同名的成员是不会产生二义性。例如:class realSet/定义一个实数集合类public:void print();class intSet/定义一个整数集合类public:void print();,void fun()intSet is;realSet rs;is.print();/调用 intSet 类中的 print()函数rs.print();/调用 realSet 类中的 print()函数显然不会引起二义性错误。返回,3.4 构造函数使用
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 对象 及其 封装
链接地址:https://www.31ppt.com/p-6329508.html