《C++程序设计语言》--第四讲 类_第1页
《C++程序设计语言》--第四讲 类_第2页
《C++程序设计语言》--第四讲 类_第3页
《C++程序设计语言》--第四讲 类_第4页
《C++程序设计语言》--第四讲 类_第5页
已阅读5页,还剩46页未读 继续免费阅读

下载本文档

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

文档简介

1、,第一节 面向对象程序设计思想 第二节 面向对象的方法 第三节 面向对象的标记 第四节 类和对象 第五节 构造函数与析构函数 第六节 类的组合 第七节 类模板,第四章 类与对象,第一节 面向对象程序设计思想,一、软件系统开发方法 现在常用的软件系统开发的方法有:传统方法、结构化方法、信息建模方法、面向对象方法。下图是系统开发方法论技术和工具:,教材中强调了两种方法: 结构化程序设计 面向对象程序设计 具体内容参看教材p95-96,二 面向对象程序设计的基本特点,面向对象软件开发方法是吸收了软件工程领域有益的概念和有效的方法而发展起来的一种软件开发方法。它集抽象性、封装性、继承性和多态性于一体,

2、可以帮助人们开发出模块化、数据抽象程度高的,体现信息隐蔽、可复用、易修改、易扩充等特性的程序。,在系统分析与设计中,抽象用来确定必要的信息系统需求,删除不必要的部分。为了突出重点,抽象有意地忽略信息系统的某些性质、属性或功能。抽象是一种突出重点、去掉细节的总结。例如:地图的抽象,根据抽象的层次,地图可分为国家地图、行政省或地区地图、城市地图、邮政代码地图等。 参看教材p97,封装或信息隐蔽,封装或信息隐蔽指软件的组成部分(模块、子程序、方法等)应该互相独立,或者隐藏设计的细节。,在系统分析和设计中,系统分析员把问题域分解为小的封装单元,这些分析和设计决定最终成为软件模块,封装就是有利于灵活地局

3、部修改和维护软件模块。,封装或信息隐蔽用于以下两种情况,1、当人们只能使用或接触整个系统的某个子集时。例如:当开发一个信息系统时,开发小组成员受命开发系统的某个部分,不需接触其它成员开发的部分。所以,封装或信息隐蔽适合于团队开发。,2. 有意防止信息系统的某些部件注意或利用系统的其它部件。这涉及到封装的另外一个方面-分配责任。正如现实生活中一个人负有某种责任,信息系统中的一个部件也有自己的责任,比如自动取款机的付钞功能,系统其它部件则担任付钞以外的其它责任。,注意:在传统方法中,封装通常局限于将功能和数据分开封装;而在面向对象的方法中,封装将功能和数据同时装入对象中。,继承,继承是表示相似性质

4、的机制。正如一个人同时继承父母的外貌特点一样,信息系统组成成分也从有关部件继承某些特点。例如:右图显示了人和教师、学生及管理者之间的继承关系。,人和教师、学生及管理者之间是继承(父子 )关系, 教师、学生、管理者之间是兄弟关系。 人的特点如姓名、性别、年龄等,为继承层次中所有子节点继承;有些特点则为子节点独有,如授课时间只对教师适用,平均分数只对学生适用,头衔只对管理者适用。同样,一些人能做的事也对教师、学生及管理者适用,例如吃饭、睡觉等,同样,有些事则为子节点独有。注意:继承在层次中是自上而下单向进行的。,多态,多态一般指具有多种形态的能力。如:水有三种形态,液体、气体和固体。在某种程度上,

5、在车里观察交通灯的反应是多态的,当交通灯闪现不同颜色时,人的反应是不同的。又如打印程序可以打印字符、数字、图形和图像,打印程序由于知道如何打印图文,因而是多态的。,第二节 面向对象的方法,面向对象是一种软件开发方法,软件开发的目的是为了进行数据处理,所以程序中包含了数据以及对数据的操作代码。面向对象的编程解决问题的思路从对象(人、地方、事情等)角度入手,而不像传统方法与结构化方法一样从功能入手。 面向对象的开发强调从问题域的概念到软件程序和界面的直接映射;心理学的研究也表明,把客观世界看成是许多对象更接近人类的自然思维方式。对象比函数更为稳定;软件需求的变动往往是功能相关的变动,而其功能的执行

6、者-对象-通常不会有大的变动。另外,面向对象的开发也支持、鼓励软件工程实践中的信息隐藏、数据抽象和封装。在一个对象内部的修改被局部隔离。面向对象开发的软件易于修改、扩充和维护。,面向对象编程-基本概念,在面向对象编程中,程序被看作是相互协作的对象集合,每个对象都是某个类的实例,所有的类构成一个通过继承关系相联系的层次结构。面向对象的语言常常具有以下特征:对象生成功能、消息传递机制、类和遗传机制。这些概念当然可以并且也已经在其他编程语言中单独出现,但只有在面向对象语言中,他们才共同出现,以一种独特的合作方式互相协作、互相补充。 过程化编程模式: 参数输入- | 代 码 | -结果输出 为实现某个

7、功能,参数被传入某个处理过程,最后传回计算结果。 面向对象编程模式: 界面 - | 对象数据结构和 操作,OO编程中,功能是通过与对象的通讯获得的。 对象可以被定义为一个封装了状态和行为的实体;或者说是数据结构(或属性)和操作。 状态实际上是为执行行为而必须存于对象之中的数据、信息。 对象的界面,也可称之为协议,是一组对象能够响应的消息的集合。 消息是对象通讯的方式,因而也是获得功能的方式。对象受到发给他的消息后,或者执行一个内部操作(有时成为方法或过程),或者再去调用其他对象的操作。所有对象都是类的实例。类是具有相同特点的对象的集合,或者也可以说,类是可用于产生对象的一个模版。对象响应一个消

8、息而调用的方法,由接受该消息的对象自己决定。 类可以以一种层次结构来安排。,第三节 面向对象的标记,参看教材p100-101,第四节 类与对象,一 类和类定义 对象和对象定义 初始化问题 静态成员 小结,一 类和类定义-1、类的声明,类和对象是面向对象程序设计(OOP)的两个最基本概念。所谓对象就是客观事物在计算机中的抽象描述;类是对具有相似属性和行为的一组对象的统一描述。 类的定义 C+的类是在结构体的基础上扩充而来的。类是把各种不同类型的数据(称为数据成员)和对数据的操作(成员函数)组织在一起而形成的用户自定义的数据类型。 C+中,类定义包括类说明和类实现两大部分。说明部分提供了对该类所有

9、数据成员和成员函数的描述,而实现部分提供了所有成员函数的实现代码。,类定义的一般形式为: class 类名 private: 数据成员或成员函数 protected: 数据成员或成员函数 public: 数据成员或成员函数 ;/注意:此处分号不要少 ,定义类时,当未指明成员是哪部分时,默认是属于private成员,但一般不要采用默认形式。,几点说明,(1)大括号的部分是类的成员(数据成员和函数成员),它们分成三部分,分别由private、public、proctected三个关键字后跟冒号来指定。这三部分可以任何顺序出现,且在一个类的定义中,这三部分并非必须同时出现。 (2)类的数据成员可以使

10、任何数据类型; (3)类的数据成员允许使用存储类型static,但其它三种存储类型不能使用; (4)类中数据成员不允许使用表达式进行初始化; (5)类中数据成员与成员函数可用const修饰。 (6)经常习惯地将类定义的说明部分或者整个定义部分(包含实现部分)放到一个头文件中。,如:下例中定义描述图书的类定义 class Record private: /private成员 char bookname20; /数据成员bookname, / 用于表示图书的名称 int number; /数据成员number,表示图书编号 public:/public成员 void regist(char *a,

11、int b); /成员函数regist,用于给 /各数据成员赋值 void show(); /成员函数show,显示各数据成员的值 ;,根据类的定义,可看出:类是实现封装的工具,所谓封装就是将类的成员按使用或存取的方式分类,有条件地限制对类成员的使用,而封装是通过public和private与成员函数实现的。private的成员构成类的内部状态,public的成员则构成与外界通信的接口,通过public的成员函数来使用private的数据成员,从而在C+中实现了封装。,2、类成员的访问控制,从访问权限上来分,类的成员又分为:公有的(public)、私有的(private)和保护的(protec

12、ted)三类。 公有的成员用public来说明,公有部分往往是一些操作(即成员函数),它是提供给用户的接口功能。这部分成员可以在程序中引用。 私有的成员用private来说明,私有部分通常是一些数据成员,这些成员是用来描述该类中的对象的属性的,用户是无法访问它们的,只有成员函数或经特殊说明的函数才可以引用它们,它们是被用来隐藏的部分。 保护的成员用protected来说明,这种成员只有该类的派生类可以访问,其余的在这个类外不能访问。保护类(protected)将在以后介绍。,类成员的访问权限表,返回,对于一个无继承关系的单一类(独立类),其访问权限可参考下图:,该类的对象,3、类成员函数的特性

13、,类的成员函数可以分为内联函数和外联函数。内联函数是指那些定义在类体内的成员函数,即该函数的函数体放在类体内。而说明在类体内,定义在类体外的成员函数叫外联函数。外联函数的函数体在类的实现部分。 引入内联函数的目的是为了解决程序中函数调用的效率问题。因为内联函数在调用时不是像一般函数那样要转去执行被调用函数的函数体,执行完成后再转回调用函数中,执行其后语句,而是在调用函数处用内联函数体的代码来替换,这样将会节省调用开销,提高运行速度。,在程序编译时,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体来进行替换。显然,这种做法不会产生转去转回的问题,但是由于在编译时将函数休中的代码被替代到

14、程序中,因此会增加目标程序代码量,进而增加空间开销,而在时间代销上不象函数调用时那么大,可见它是以目标代码的增加为代价来换取时间的节省。 内联函数的定义方法内联函数的定义方法与一般函数一样,只是在函数定义的头前加上关键字inline即可。如: inline int add_int (int x, int y, int z) return x+y+z; ,返回,二 对象和对象定义-1、对象的创建,类是抽象的概念,而对象是具体的,类只是一种数据类型,而对象是属于该类(数据类型)的一个变量,占用了各自的存储单元,每个对象各自具有了该类的一套数据成员(静态成员除外),而所有成员函数是所有对象共有的。每

15、个对象的函数成员都通过指针指向同一个代码空间。(参看教材p124图) 对象的定义格式: (1)class 类名 对象1,对象2, ,对象n ; (2)类名 对象1,对象2, ,对象n ; (3)类名 对象1(参数表), ,对象n (参数表) ; 如: TDate date1, date2, *Pdate, date31;,2、对象成员的使用,访问对象的成员包括读写对象的数据成员和调用它的成员函数,其访问格式是: . 或者 .() 前者用来表示数据成员的,后者用来表示成员函数的。如:上例中已定义了类Record,则: Record book1,book2; /此处的book1,book2就是Re

16、cord /类型,也就是类的两个对象 可参看教材p125程序5-3-1,如上例中,对象的主函数如下: void main() Record book1,book2; /定义对象book1和book2 /调用成员函数regist,给book1的两个数据成员 /bookname和number赋值 book1.regist(“C+编程教程”, 1001); /调用成员函数regist,给book2的两个数据成员赋值 book2.regist(“C+语言参考”, 1002); /调用成员函数show,显示book1对象的数据成员 /bookname和number的值 book1.show(); /调用

17、成员函数show,显示book2对象的数据成员 /bookname和number的值 book2.show(); ,如改为下面的代码,则错误: void main() Record book1,book2; /由于bookname和number是类Record的私有成员,在类外不能直接使用,即对象不能直接使用。 strcpy(book1.bookname,“C+编程教程”); book1.number=1001; strcpy(book2.bookname,“C+语言参考”); book2.number=1002; book1.show(); book2.show(); ,访问对象的成员需注意

18、以下几点:,对于类的私有成员,只能通过其成员函数来访问,不能在类外对私有成员访问。 2. 调用成员函数时要在函数名之前加上对象名和.即可,即先指明对象,再指明成员。也可以采用指向对象的指针来访问,但要在函数名前加上指针变量名和“-”。 3. 任何对对象私有数据的访问都必须通过向对象发送消息来实现,而且所发送的消息还必须是该对象能够识别和接受的。在C+中,消息发送正是通过公有成员函数的调用来实现的。由于类接口隐藏了对象的内部细节,用户只能通过类接口访问对象,因此,在类设计中必须提供足够的公有接口以捕获对象的全部行为,这正是类设计中的一个最基本的要求。,返回,3、对象数组,参看教材p305-306

19、,第五节 构造函数河析构函数,全局变量和静态变量在定义时,将自动赋初值为0;局部变量在定义时,其初始值不固定的。而当对象被定义时,由于对象的意义表达了现实世界的实体,所以一旦定义对象,就必须有一个有意义的初始值,在C+中,在定义对象的同时,给该对象初始化的方法就是利用构造函数。下面分别从三个方面讲述初始化问题: 1、类中数据成员的初始化:构造函数和析构函数 由于在类的定义中不能对数据成员初始化,那么类中数据成员利用构造函数进行初始化。 2、类中常量和引用的初始化:初始化表 3、类中数据成员的初始化:初始化表 4、类的对象初始化:拷贝构造函数,1、构造函数和析构函数,构造函数和析构函数是在类体中

20、说明的两种特殊的成员函数。构造函数的功能是在创建对象时,使用给定的值来将对象初始化。析构函数的功能是用来释放一个对象的,在对象删除前,用它来做一些清理工作,它与构造函数的功能正好相反。 下面举一例子来说明构造函数和析构函数的特点: 程序5-1,class TDatepublic: TDate(int y, int m, int d); TDate(); int IsLeapYear(); void Print();private: int year, month, day;,/类的实现部分TDate:TDate(int y, int m, int d) year = y; month = m;

21、 day = d; cout构造函数已被调用。n;TDate:TDate() cout析构函数被调用。n;int TDate:IsLeapYear() return(year%4=0 ,构造函数的特点如下:,1) 构造函数是成员函数,函数体可写在类体内,也可定在类体外。2) 构造函数是一个特殊的函数, 该函数的名字与类名相同; 该函数不指定类型说明,它有隐含的返回值,该值由系统内部使用。 该函数可以一个参数,也可以有多个参数。3)可以定义多个构造函数。即构造函数可以重载,也就是可以定义多个参数个数不同的函数。.。 4) 程序中不能直接调用构造函数,在创建对象时系统自动调用构造函数。,析构函数的

22、特点如下:,1)析构函数是成员函数,函数体可写在类体内,也可定在类体外。 2)析构函数也是一个特殊的函数 它的名字同类名,并在前面加“”字符,用来与构造函数加以区别; 析构函数不指定数据类型,并且也没有参数。 3)一个类中只可能定义一个析构函数。 4)析构函数可以被调用,也可以系统调用。在下面两种情况下,析构函数会被自动调用。 如果一个对象被定义在一个函数体内,则当这个函数结束时,该对象的析构函数被自动调用。 当一个对象是使用new运算符被动态创建的,在使用delete运算符释放它时,delete将会自动调用析构函数。,缺省构造函数和缺省析构函数,在类定义时没有定义任何构造函数时,则编译器自动

23、生成一个不带参数的缺省构造函数,其格式如下: :() 同理,如果一个类中没有定义析构函数时,则编译系统也生成一个称为缺省析构函数,缺省析构函数是一个空函数,其格式如下: : ,2、类中常量和引用的初始化,上一小节讲述了应用析构函数对数据成员变量的初始化,那么如何初始化常量和引用?(应用初始化表,注意在类定义中不能直接用。),返回,#include class initi_data private: int x; int ,结果: x= 100, rx=100, pi=3.14,那么,从左边例子中可以看出,初始化表的格式: 析构函数:引用名(变量),常量名(常数), ,3、类中对象成员的初始化,

24、1. 对象成员的概念 C+中允许将一个已定义的类的对象作为另一个类的数据成员,这称为类的组合。当一个类的成员是某一个类的对象时,则称该对象为对象成员(或子对象)。如:class A ;class Bprivate: A a; public: ;,在类中出现了子对象或称对象成员时,该类的构造函数要包含对子对象的初始化,通常采用成员初始化表的方法来初始化子对象。在成员初始化表中包含对子对象的初始化和对类中其他成员的初始化。下面举一例子说明成员初始化的构造。,#include class A private: int A1, A2; public: A(int i, int j) A1=i; A2=

25、j; void print() coutA1“,”A2endl; ;class Bprivate: A a; /对象成员 int b;public: B(int i, int j, int k):a(i, j), b(k) void print();,void B:print() a.print(); coutbendl;void main() B b(6, 7, 8); b.print();,该程序的输出结果为: 6,7 8,其中,a(i, j), b(k)是成员初始化表,它有二项,前一项是给子对象a初始化,其格式如下: () 后一项是给类B的数据成员b初始化。这一项也可以写在构造函数的函数

26、体内,使用赋值表达式语句b = k; 给类B的数据成员初始化。,4、类的对象初始化,拷贝构造函数是C+中引入的一种新的构造函数。定义一个拷贝构造函数的方式是: 类名(const 类名 2)当对象作为函数实参传递给函数形参时,如:上例 P = f(N); 3)当对象用为函数返回值时。 如果类中没有说明拷贝初始化构造函数,则编译系统自动生成一个具有上术形式的缺省拷贝初始化构造函数。作为该类的公有成员。,实例,Example是一个人员信息类。用普通构造函数生成obj1,用拷贝构造函数生成obj2。 # include # include class Example private: char *na

27、me; int num; public: example(int i, char *str ) / 构造函数定义 name=str; num=i; ,example(const Example /显示obj2的值 /其它程序部分 ,程序的执行结果是: 数据成员num的值=215 数据成员num的值=215 说明: (1)上例中在main函数中的语句Example obj2(obj1);在执行时,系统会自动调用类Example的拷贝构造函数完成对obj2对象的构造。 (2)如果程序员没有为所设计的类提供显式的拷贝构造函数,则系统会自动提供一个默认的拷贝构造函数,其功能是:把作为参数的对象的数据成员逐个拷贝到目标变量中,这称为成

温馨提示

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

评论

0/150

提交评论