《中国高等院校计算机基础教育课程体系规划教材讲授第8章》由会员分享,可在线阅读,更多相关《中国高等院校计算机基础教育课程体系规划教材讲授第8章(72页珍藏版)》请在金锄头文库上搜索。
1、中国高等院校计算机中国高等院校计算机基础教育课程体系规基础教育课程体系规划教材讲授划教材讲授-第第8章章第第8章章 类和对象类和对象8.1 面向对象程序设计方法概述面向对象程序设计方法概述8.2 类的声明和对象的定义类的声明和对象的定义8.3 类的成员函数类的成员函数8.4 对象成员的引用对象成员的引用8.5 类的封装性和信息隐蔽类的封装性和信息隐蔽8.6 类和对象的简单应用举例类和对象的简单应用举例面向对象的程序设计的思路和人们日常生活中处理问面向对象的程序设计的思路和人们日常生活中处理问题的思路是相似的。在自然世界和社会生活中,一个题的思路是相似的。在自然世界和社会生活中,一个复杂的事物总
2、是由许多部分组成的。复杂的事物总是由许多部分组成的。当人们生产汽车时,分别设计和制造发动机、底盘、当人们生产汽车时,分别设计和制造发动机、底盘、车身和轮子,最后把它们组装在一起。在组装时,各车身和轮子,最后把它们组装在一起。在组装时,各部分之间有一定的联系,以便协调工作。部分之间有一定的联系,以便协调工作。这就是面向对象的程序设计的基本思路。这就是面向对象的程序设计的基本思路。为了进一步说明问题,下面先讨论几个有关的概念。为了进一步说明问题,下面先讨论几个有关的概念。8.1 面向对象程序设计方法概述面向对象程序设计方法概述8.1.1 什么是面向对象的程序设计什么是面向对象的程序设计1. 对象对
3、象客观世界中任何一个事物都可以看成一个对象客观世界中任何一个事物都可以看成一个对象(object)。对象可大可小。对象可大可小。对象是构成系统的基本单位对象是构成系统的基本单位。任何一个对象都应当具有这两个要素,即任何一个对象都应当具有这两个要素,即属性属性(attribute)和和行为行为(behavior),它能根据外界给的它能根据外界给的信息进行相应的操作。信息进行相应的操作。一个对象往往是由一组属性和一个对象往往是由一组属性和一组行为构成的。一般来说,凡是具备属性和行为这一组行为构成的。一般来说,凡是具备属性和行为这两种要素的,都可以作为对象。两种要素的,都可以作为对象。在一个系统中的
4、多个对象之间通过一定的渠道相互联在一个系统中的多个对象之间通过一定的渠道相互联系,如图系,如图8.1示意。示意。要使某一个对象实现某一种行为要使某一个对象实现某一种行为(即操作即操作),应当向它传送相应的消息。对象之间就是,应当向它传送相应的消息。对象之间就是这样通过这样通过发送和接收消息发送和接收消息互相联系的。互相联系的。图图8.1 图图8.2 使用面向对象的程序设计方法设计一个复杂的软件使用面向对象的程序设计方法设计一个复杂的软件系统时,首要的问题是确定该系统是由哪些对象组成系统时,首要的问题是确定该系统是由哪些对象组成的,并且设计这些对象。的,并且设计这些对象。在在C+中,每个对象都是
5、由中,每个对象都是由数据和函数数据和函数(即操作代码即操作代码)这两部分组成的这两部分组成的,见图见图8.2。数据体现了前面提到的数据体现了前面提到的“属性属性”,如一个三角形对象,如一个三角形对象,它的它的3个边长就是它的属性。个边长就是它的属性。函数是用来对数据进行函数是用来对数据进行操作的,以便实现某些功能,操作的,以便实现某些功能,例如可以通过边长计算例如可以通过边长计算出三角形的面积,并且输出三角形的边长和面积。计出三角形的面积,并且输出三角形的边长和面积。计算三角形面积和输出有关数据就是前面提到的行为,算三角形面积和输出有关数据就是前面提到的行为,在程序设计方法中也称为在程序设计方
6、法中也称为方法方法(method)。调用对象中调用对象中的函数就是向该对象传送一个消息的函数就是向该对象传送一个消息(message),要求要求该对象实现某一行为该对象实现某一行为(功能功能)。2. 封装与信息隐蔽封装与信息隐蔽对一个对象进行封装处理,把它的一部分属性和功能对一个对象进行封装处理,把它的一部分属性和功能对外界屏蔽,也就是说从外界是看不到的对外界屏蔽,也就是说从外界是看不到的,甚至是不甚至是不可知的。可知的。面向对象程序设计的一个重要特点就是面向对象程序设计的一个重要特点就是“封装性封装性” 所谓所谓“封装封装”,指两方面的含义:,指两方面的含义: 一是将有关的数据和操作代码封装
7、在一个对象中,形成一个一是将有关的数据和操作代码封装在一个对象中,形成一个基本单位,各个对象之间相对独立,互不干扰。基本单位,各个对象之间相对独立,互不干扰。二是将对象中某些部分对外隐蔽,即隐蔽其内部细节,只留二是将对象中某些部分对外隐蔽,即隐蔽其内部细节,只留下少量接口,以便与外界联系,接收外界的消息。下少量接口,以便与外界联系,接收外界的消息。这种对外这种对外界隐蔽的做法称为界隐蔽的做法称为信息隐蔽信息隐蔽。信息隐蔽还有利于数据安全,信息隐蔽还有利于数据安全,防止无关的人了解和修改数据。防止无关的人了解和修改数据。C+的对象中的函数名就是对象的的对象中的函数名就是对象的对外接口对外接口,外
8、界可外界可以通过函数名来调用这些函数来实现某些行为以通过函数名来调用这些函数来实现某些行为(功能功能)。这些将在以后详细介绍。这些将在以后详细介绍。3. 抽象抽象在程序设计方法中,常用到在程序设计方法中,常用到抽象抽象(abstraction)这一这一名词。名词。抽象的过程是将有关事物的共性归纳、集中的抽象的过程是将有关事物的共性归纳、集中的过程。过程。抽象的作用是表示同一类事物的本质抽象的作用是表示同一类事物的本质。C和和C+中的中的数据类型就是对一批具体的数的抽象。数据类型就是对一批具体的数的抽象。对象是具体存在的,如一个三角形可以作为一个对象,对象是具体存在的,如一个三角形可以作为一个对
9、象,10个不同尺寸的三角形是个不同尺寸的三角形是10个对象。如果这个对象。如果这10个三角个三角形对象有相同的属性和行为,可以将它们抽象为一种形对象有相同的属性和行为,可以将它们抽象为一种类型,称为三角形类型。在类型,称为三角形类型。在C+中,这种类型就称为中,这种类型就称为“类类(class)”。这这10个三角形就是属于同一个三角形就是属于同一“类类”的对象。的对象。类是对象的抽象,而对象则是类的特例,或类是对象的抽象,而对象则是类的特例,或者说是类的具体表现形式。者说是类的具体表现形式。4. 继承与重用继承与重用如果在软件开发中已经建立了一个名为如果在软件开发中已经建立了一个名为A的的“类
10、类”,又想另外建立一个名为又想另外建立一个名为B的的“类类”,而后者与前者内,而后者与前者内容基本相同,只是在前者的基础上增加一些属性和行容基本相同,只是在前者的基础上增加一些属性和行为,只需在类为,只需在类A的基础上增加一些新内容即可。这就的基础上增加一些新内容即可。这就是面向对象程序设计中的是面向对象程序设计中的继承机制继承机制。利用继承可以简利用继承可以简化程序设计的步骤。化程序设计的步骤。“卡车卡车”继承了继承了“汽车汽车”的基本特征,又增加了新的的基本特征,又增加了新的特征,特征,“汽车汽车”是父类,或称为基类,是父类,或称为基类,“卡车卡车”是从是从“汽车汽车”派生出来的,称为子类
11、或派生类。派生出来的,称为子类或派生类。C+提供了继承机制,采用继承的方法可以很方便地提供了继承机制,采用继承的方法可以很方便地利用一个已有的类建立一个新的类。这就是常说的利用一个已有的类建立一个新的类。这就是常说的“软件重用软件重用”(software reusability) 的思想。的思想。5. 多态性多态性如果有几个相似而不完全相同的对象,有时人们要求如果有几个相似而不完全相同的对象,有时人们要求在向它们发出同一个消息时,它们的反应各不相同,在向它们发出同一个消息时,它们的反应各不相同,分别执行不同的操作。这种情况就是分别执行不同的操作。这种情况就是多态现象多态现象。如,如,在在Win
12、dows环境下,用鼠标双击一个文件对象环境下,用鼠标双击一个文件对象(这就这就是向对象传送一个消息是向对象传送一个消息),如果对象是一个可执行文,如果对象是一个可执行文件,则会执行此程序,如果对象是一个文本文件,则件,则会执行此程序,如果对象是一个文本文件,则启动文本编辑器并打开该文件。启动文本编辑器并打开该文件。在在C+中,所谓多态性中,所谓多态性(polymorphism)是指:是指: 由继由继承而产生的相关的不同的类,其对象对同一消息会作承而产生的相关的不同的类,其对象对同一消息会作出不同的响应。出不同的响应。多态性是面向对象程序设计的一个重多态性是面向对象程序设计的一个重要特征,能增加
13、程序的灵活性。要特征,能增加程序的灵活性。传统的面向过程程序设计是围绕功能进行的,用一个传统的面向过程程序设计是围绕功能进行的,用一个函数实现一个功能。所有的数据都是公用的,一个函函数实现一个功能。所有的数据都是公用的,一个函数可以使用任何一组数据,而一组数据又能被多个函数可以使用任何一组数据,而一组数据又能被多个函数所使用数所使用(见图(见图8.3)。)。 图图8.38.1.2 面向对象程序设计的特点面向对象程序设计的特点面向对象程序设计采取的是另外一种思路。它面对的面向对象程序设计采取的是另外一种思路。它面对的是一个个对象。实际上,每一组数据都是有特定的用是一个个对象。实际上,每一组数据都
14、是有特定的用途的,是某种操作的对象。也就是说,一组操作调用途的,是某种操作的对象。也就是说,一组操作调用一组数据。一组数据。程序设计者的任务包括程序设计者的任务包括两个方面两个方面: 一一 设计所需的各种类和对象,即决定把哪些数据和设计所需的各种类和对象,即决定把哪些数据和操作封装在一起;操作封装在一起;二二 考虑怎样向有关对象发送消息,以完成所需的任考虑怎样向有关对象发送消息,以完成所需的任务。务。 类是类是C+中十分重要的概念,它是实现面向对象程序中十分重要的概念,它是实现面向对象程序设计的基础。类是所有面向对象的语言的共同特征,设计的基础。类是所有面向对象的语言的共同特征,所有面向对象的
15、语言都提供了这种类型。所有面向对象的语言都提供了这种类型。 在本章到第在本章到第10章将介绍章将介绍基于对象的程序设计基于对象的程序设计。包括。包括类和对象的概念类和对象的概念、类的机制和声明类的机制和声明、类对象的定义与类对象的定义与使用使用等。这是面向对象的程序设计的基础。等。这是面向对象的程序设计的基础。8.1.3 类和对象的作用类和对象的作用随着软件规模的迅速增大,软件人员面临的问题十分随着软件规模的迅速增大,软件人员面临的问题十分复杂。需要规范整个软件开发过程,明确软件开发过复杂。需要规范整个软件开发过程,明确软件开发过程中每个阶段的任务,在保证前一个阶段工作的正确程中每个阶段的任务
16、,在保证前一个阶段工作的正确性的情况下,再进行下一阶段的工作。这就是软件工性的情况下,再进行下一阶段的工作。这就是软件工程学需要研究和解决的问题。程学需要研究和解决的问题。面向对象的软件工程包括以下几个部分面向对象的软件工程包括以下几个部分: 8.1.4 面向对象的软件开发面向对象的软件开发1. 面向对象分析面向对象分析(object oriented analysis,OOA) 软件工程中的系统分析阶段,系统分析员要和用户结软件工程中的系统分析阶段,系统分析员要和用户结合在一起,做出需求分析,合在一起,做出需求分析, 概括出系统动能和任务。概括出系统动能和任务。面向对象的分析,面向对象的分析
17、, 按照面向对象的概念和方法,在按照面向对象的概念和方法,在 归纳出有关的对象归纳出有关的对象(包括对象的属性和行为包括对象的属性和行为)以及对象以及对象之间的联系,并将具有相同属性和行为的对象用一个之间的联系,并将具有相同属性和行为的对象用一个类类(class)来表示。建立一个能反映真实工作情况的来表示。建立一个能反映真实工作情况的需求模型。需求模型。2. 面向对象设计面向对象设计(object oriented design,OOD)根据面向对象分析阶段形成的需求模型,对每一部分根据面向对象分析阶段形成的需求模型,对每一部分分别进行具体的设计,首先是进行类的设计,类的设分别进行具体的设计,
18、首先是进行类的设计,类的设计可能包含多个层次计可能包含多个层次(利用继承与派生利用继承与派生)。然后以这些。然后以这些类为基础提出程序设计的思路和方法,包括对算法的类为基础提出程序设计的思路和方法,包括对算法的设计。设计。 3. 面向对象编程面向对象编程(object oriented programming,OOP)根据面向对象设计的结果,用一种计算机语言把它写根据面向对象设计的结果,用一种计算机语言把它写成程序,显然应当选用面向对象的计算机语言成程序,显然应当选用面向对象的计算机语言(例如例如C+),否则无法实现面向对象设计的要求。否则无法实现面向对象设计的要求。4. 面向对象测试面向对象
19、测试(object oriented test,OOT)在写好程序后交给用户使用前,必须对程序进行严格在写好程序后交给用户使用前,必须对程序进行严格的测试。测试的目的是发现程序中的错误并改正它。的测试。测试的目的是发现程序中的错误并改正它。 5. 面向对象维护面向对象维护(object oriented soft maintenance,OOSM)因为对象的封装性,修改一个对象对其他对象影响很因为对象的封装性,修改一个对象对其他对象影响很小。利用面向对象的方法维护程序,大大提高了软件小。利用面向对象的方法维护程序,大大提高了软件维护的效率。维护的效率。每一个实体都是对象。有一些对象是具有相同的
20、结构和特性每一个实体都是对象。有一些对象是具有相同的结构和特性的。每个对象都属于一个特定的类型。的。每个对象都属于一个特定的类型。在在C+中对象的类型称为中对象的类型称为类类(class)。类代表了某一批对象的类代表了某一批对象的共性和特征。共性和特征。前面已说明:前面已说明: 类是对象的抽象,而对象是类的类是对象的抽象,而对象是类的具体实例具体实例(instance)。在在C+中也是先声明一个类类型,然后用它去定义若干个同类中也是先声明一个类类型,然后用它去定义若干个同类型的对象。对象就是类类型的一个变量。可以说类是对象的型的对象。对象就是类类型的一个变量。可以说类是对象的模板,是用来定义对
21、象的一种抽象类型。模板,是用来定义对象的一种抽象类型。类是抽象的,不占用内存,而对象是具体的,占用存储空间。类是抽象的,不占用内存,而对象是具体的,占用存储空间。8.2 类的声明和对象的定义类的声明和对象的定义 8.2.1 类和对象的关系类和对象的关系类是用户自己指定的类型。如果程序中要用到类类型,类是用户自己指定的类型。如果程序中要用到类类型,必须自己根据需要进行声明,或者使用别人已设计好必须自己根据需要进行声明,或者使用别人已设计好的类。的类。在在C+中声明一个类类型和声明一个结构体类型是相中声明一个类类型和声明一个结构体类型是相似的。似的。下面是声明一个结构体类型的方法:下面是声明一个结
22、构体类型的方法: struct Student /声明了一个名为声明了一个名为Student的结构体类型的结构体类型 int num;char name20;char sex;Student stud1,stud2; /定义了两个结构体变量定义了两个结构体变量stud1和和stud28.2.2 声明类类型声明类类型它只包括数据,没有包括操作。现在声明一个类:它只包括数据,没有包括操作。现在声明一个类: class Student /以以class开头开头 int num;char name20; char sex; /以上以上3行是数据成员行是数据成员 void display( ) /这是成
23、员函数这是成员函数coutnum:numendl;coutname:nameendl; coutsex:sexendl; /以上以上4行是函数中的操作语句行是函数中的操作语句 ;Student stud1,stud2; /定义了两个定义了两个Student 类的对象类的对象stud1和和stud2 可以看到声明类的方法是由声明结构体类型的方法发可以看到声明类的方法是由声明结构体类型的方法发展而来的。展而来的。类类(class)就是对象的类型。实际上,类是一种广义就是对象的类型。实际上,类是一种广义的数据类型。的数据类型。类这种数据类型中的数据既包含数据,类这种数据类型中的数据既包含数据,也包含
24、操作数据的函数。也包含操作数据的函数。不能把类中的全部成员与外界隔离,不能把类中的全部成员与外界隔离,一般是把数据隐一般是把数据隐蔽起来,而把成员函数作为对外界的接口。蔽起来,而把成员函数作为对外界的接口。可以将上面类的声明改为可以将上面类的声明改为class Student /声明类类型声明类类型 private: /声明以下部分为私有的声明以下部分为私有的int num;char name20; char sex; public: /声明以下部分为公用的声明以下部分为公用的void display( ) coutnum:numendl;coutname:nameendl;coutsex:s
25、exendl; ;Student stud1,stud2; /定义了两个定义了两个Student 类的对象类的对象如果在类的定义中既不指定如果在类的定义中既不指定private,也不指定也不指定public,则系统就默认为是私有的。则系统就默认为是私有的。归纳以上对类类型的声明,可得到其一般形式如下:归纳以上对类类型的声明,可得到其一般形式如下: class 类名类名 private:私有的数据和成员函数私有的数据和成员函数; public:公用的数据和成员函数公用的数据和成员函数;private和和public称为成员访问限定符称为成员访问限定符(member access specifie
26、r)。除了除了private和和public之外,还有一种成员访问限定符之外,还有一种成员访问限定符protected(受保护的受保护的),用用protected声明的成员称为受声明的成员称为受保护的成员,它不能被类外访问保护的成员,它不能被类外访问(这点与私有成员类这点与私有成员类似似),但可以被派生类的成员函数访问,但可以被派生类的成员函数访问。如果在类体中既不写如果在类体中既不写private,又不写又不写public,系统系统默默认为认为private。在一个类体中,关键字在一个类体中,关键字private和和public可以分别出现可以分别出现多次。每个部分的有效范围到出现另一个访问
27、限定符多次。每个部分的有效范围到出现另一个访问限定符或类体结束时或类体结束时(最后一个右花括号最后一个右花括号)为止。为止。但是为了使但是为了使程序清晰,应该养成这样的习惯:程序清晰,应该养成这样的习惯: 使每一种成员访使每一种成员访问限定符在类定义体中只出现一次。问限定符在类定义体中只出现一次。 在在C+程序中,经常可以看到类。程序中,经常可以看到类。为了用户方便为了用户方便,常常用的用的C+编译系统往往向用户提供类库编译系统往往向用户提供类库(但不属于但不属于C+语言的组成部分语言的组成部分),内装常用的基本的类,供用,内装常用的基本的类,供用户使用。不少用户也把自己或本单位经常用到的类放
28、户使用。不少用户也把自己或本单位经常用到的类放在一个专门的类库中,需要用时直接调用,这样就减在一个专门的类库中,需要用时直接调用,这样就减少了程序设计的工作量。少了程序设计的工作量。8.2.2节的程序段中,最后一行用已声明的节的程序段中,最后一行用已声明的Student类类来定义对象,这种方法是很容易理解的。经过定义后,来定义对象,这种方法是很容易理解的。经过定义后,stud1和和stud2就成为具有就成为具有Student类特征的对象。类特征的对象。stud1和和stud2这两个对象都分别包括这两个对象都分别包括Student类中定义类中定义的数据和函数。的数据和函数。定义对象也可以有几种方
29、法。定义对象也可以有几种方法。8.2.3 定义对象的方法定义对象的方法1. 先声明类类型,然后再定义对象先声明类类型,然后再定义对象前面用的就是这种方法,如前面用的就是这种方法,如Student stud1,stud2; /Student是已经声明的类类型是已经声明的类类型在在C+中,声明了类类型后,定义对象如下。中,声明了类类型后,定义对象如下。类名类名 对象名对象名 Student stud1,stud2;直接用类名定义对象。这两种方法是等效的。直接用类名定义对象。这两种方法是等效的。 2. 在声明类类型的同时定义对象在声明类类型的同时定义对象class Student /声明类类型声明类
30、类型 public: /先声明公用部分先声明公用部分 void display( ) coutnum:numendl;coutname:nameendl;coutsex:sexendl; private: /后声明私有部分后声明私有部分int num;char name20; char sex; stud1,stud2; /定义了两个定义了两个Student类的对象类的对象在定义在定义Student类的同时,定义了两个类的同时,定义了两个Student 类的对类的对象。象。3. 不出现类名,直接定义对象不出现类名,直接定义对象class /无类名无类名private: /声明以下部分为私有的声
31、明以下部分为私有的 public: /声明以下部分为公用的声明以下部分为公用的 stud1,stud2; /定义了两个无类名的类定义了两个无类名的类对象对象直接定义对象,在直接定义对象,在C+中是合法的、允许的。中是合法的、允许的。前面讲结构体时也有过类似的定义方法,前面讲结构体时也有过类似的定义方法,不提倡用不提倡用类的成员函数类的成员函数(简称类函数简称类函数)是函数的一种,它的用法是函数的一种,它的用法和作用和第和作用和第4章介绍过的函数基本上是一样的,它也章介绍过的函数基本上是一样的,它也有返回值和函数类型,有返回值和函数类型,它与一般函数的区别只是:它与一般函数的区别只是: 它是属于
32、一个类的成员,出现在类体中。它可以被指它是属于一个类的成员,出现在类体中。它可以被指定为定为private(私有的私有的)、public(公用的公用的)或或protected(受受保护的保护的)。在使用类函数时,要在使用类函数时,要注意调用它的权限注意调用它的权限(它它能否被调用能否被调用)以及它的以及它的作用域作用域(函数能使用什么范围中函数能使用什么范围中的数据和函数的数据和函数)。8.3 类的成员函数类的成员函数 8.3.1 成员函数的性质成员函数的性质 私有的成员函数只能被本类中的其他成员函数所调私有的成员函数只能被本类中的其他成员函数所调用,而不能被类外调用。用,而不能被类外调用。成
33、员函数可以访问本类中任何成员成员函数可以访问本类中任何成员(包括私有的和公包括私有的和公用的用的),可以引用在本作用域中有效的数据,可以引用在本作用域中有效的数据。一般的做法是将需要被外界调用的成员函数指定为一般的做法是将需要被外界调用的成员函数指定为public,它们是类的对外接口。它们是类的对外接口。但应注意,但应注意,并非要求并非要求把所有成员函数都指定为把所有成员函数都指定为public。有的函数并不是准有的函数并不是准备为外界调用的,而是为本类中的成员函数所调用的,备为外界调用的,而是为本类中的成员函数所调用的,就应该将它们指定为就应该将它们指定为private。这种函数的作用是支持
34、这种函数的作用是支持其他函数的操作,是类中其他成员的其他函数的操作,是类中其他成员的工具函数工具函数,类外类外用户不能调用这些私有的工具函数。用户不能调用这些私有的工具函数。 在前面已经看到成员函数是在类体中定义的。也可以在前面已经看到成员函数是在类体中定义的。也可以在类体中只写成员函数的声明,而在类的外面进行函在类体中只写成员函数的声明,而在类的外面进行函数定义。如数定义。如 class Student public:void display( ); /公用成员函数原型声明公用成员函数原型声明private:int num;string name; char sex; /以上以上3行是私有数
35、据成员行是私有数据成员 ;void Student display( ) /在类外定义在类外定义display类函数类函数coutnum:numendl; /函数体函数体coutname:nameendl; coutsex:sexendl; Student stud1,stud2; /定义两个类对象定义两个类对象8.3.2 在类外定义成员函数在类外定义成员函数注意:注意: 在类体中直接定义函数时,不需要在函数名在类体中直接定义函数时,不需要在函数名前面加上类名,因为函数属于哪一个类是不言而喻的。前面加上类名,因为函数属于哪一个类是不言而喻的。成员函数在类外定义时,必须在函数名前面加上类名,成员
36、函数在类外定义时,必须在函数名前面加上类名,予以限定予以限定(qualifed),“ ”是作用域限定符是作用域限定符(field qualifier)或称作用域运算符,或称作用域运算符,用它声明函数是属于哪用它声明函数是属于哪个类的。个类的。如果在作用域运算符如果在作用域运算符“ ”的前面没有类名,或者函的前面没有类名,或者函数名前面既无类名又无作用域运算符数名前面既无类名又无作用域运算符“ ”,如,如 display( ) 或或 display( )表示表示display函数不属于任何类,这个函数不是成员函函数不属于任何类,这个函数不是成员函数,而是全局函数,即非成员函数的一般普通函数。数,
37、而是全局函数,即非成员函数的一般普通函数。类函数必须先在类体中作原型声明,然后在类外定义,类函数必须先在类体中作原型声明,然后在类外定义,也就是说类体的位置应在函数定义之前,否则编译时也就是说类体的位置应在函数定义之前,否则编译时会出错会出错。虽然函数在类的外部定义,但在调用成员函数时会根虽然函数在类的外部定义,但在调用成员函数时会根据在类中声明的函数原型找到函数的定义(函数代码)据在类中声明的函数原型找到函数的定义(函数代码),从而执行该函数。,从而执行该函数。在类的内部对成员函数作声明,而在类体外定义成员在类的内部对成员函数作声明,而在类体外定义成员函数,这是程序设计的一种良好习惯。函数,
38、这是程序设计的一种良好习惯。如果一个函数,函数体小,可以在类中定义,函数体如果一个函数,函数体小,可以在类中定义,函数体大,应该在类外进行定义。大,应该在类外进行定义。关于关于内置内置(inline)函数函数,已在第,已在第4章第章第4.5节中作过介节中作过介绍。类的成员函数也可以指定为内置函数。绍。类的成员函数也可以指定为内置函数。在类体中定义的成员函数的规模一般都很小,而系统在类体中定义的成员函数的规模一般都很小,而系统调用函数的过程所花费的时间开销相对是比较大的。调用函数的过程所花费的时间开销相对是比较大的。调用一个函数的时间开销远远大于小规模函数体中全调用一个函数的时间开销远远大于小规
39、模函数体中全部语句的执行时间。部语句的执行时间。为了减少时间开销,如果在类体为了减少时间开销,如果在类体中定义的成员函数中不包括循环等控制结构,中定义的成员函数中不包括循环等控制结构,C+系系统会自动将它们作为内置统会自动将它们作为内置(inline)函数来处理。也就函数来处理。也就是说,在程序调用这些成员函数时,并不是真正地执是说,在程序调用这些成员函数时,并不是真正地执行函数的调用过程行函数的调用过程(如保留返回地址等处理如保留返回地址等处理),而是把,而是把函数代码嵌入程序的调用点。这样可以大大减少调用函数代码嵌入程序的调用点。这样可以大大减少调用成员函数的时间开销。成员函数的时间开销。
40、8.3.3 inline 成员函数成员函数C+要求对一般的内置函数要用关键字要求对一般的内置函数要用关键字inline声明,声明,但对类内定义的成员函数,可以省略但对类内定义的成员函数,可以省略inline,因为这因为这些成员函数已被隐含地指定为内置函数。些成员函数已被隐含地指定为内置函数。如如 class Student public: void display( ) coutnum:numendl;coutname:nameendl; coutsex:sexendl; private:int num;string name; char sex;其中第其中第3行行void display(
41、)也可以写成也可以写成inline void display( )将将display函数显式地声明为内置函数。以上两种写法函数显式地声明为内置函数。以上两种写法是等效的。对在类体内定义的函数,一般都省写是等效的。对在类体内定义的函数,一般都省写inline。应该注意的是:应该注意的是: 如果成员函数不在类体内定义,而如果成员函数不在类体内定义,而在类体外定义,系统并不把它默认为内置在类体外定义,系统并不把它默认为内置(inline)函函数,调用这些成员函数的过程和调用一般函数的过程数,调用这些成员函数的过程和调用一般函数的过程是相同的。如果想将这些成员函数指定为内置函数,是相同的。如果想将这些
42、成员函数指定为内置函数,应当应当用用inline作显式声明作显式声明。如如class Student public:inline void display( ); /声明此成员函数为内置函数声明此成员函数为内置函数private:int num;string name; char sex; ;inline void Student display( ) / 在类外定义在类外定义display函数为内置函数函数为内置函数coutnum:numendl; coutname:nameendl; coutsex:sexabc;可以用下面的语句来输出该类对象所占用的字节数可以用下面的语句来输出该类对象所
43、占用的字节数:coutsizeof(Time)endl;输出的值是输出的值是12。这就证明了一个对象所占的空间大小。这就证明了一个对象所占的空间大小只取决于该对象中数据成员所占的空间,而与成员函只取决于该对象中数据成员所占的空间,而与成员函数无关。数无关。需要注意的是:需要注意的是: 虽然调用不同对象的成员函数时都虽然调用不同对象的成员函数时都是执行同一段函数代码,但是执行结果一般是不相同是执行同一段函数代码,但是执行结果一般是不相同的。不同的对象使用的是同一个函数代码段,它怎么的。不同的对象使用的是同一个函数代码段,它怎么能够分别对不同对象中的数据进行操作呢?原来能够分别对不同对象中的数据进
44、行操作呢?原来C+为此专门设立了一个名为为此专门设立了一个名为this的指针,用来指向不同的指针,用来指向不同的对象的对象。需要说明:需要说明: (1) 不论成员函数在类内定义还是在类外定义,成员不论成员函数在类内定义还是在类外定义,成员函数的代码段都用同一种方式存储。函数的代码段都用同一种方式存储。(2) 不要将成员函数的这种存储方式和不要将成员函数的这种存储方式和inline(内置内置)函函数的概念混淆。数的概念混淆。(3) 应当说明:应当说明: 常说的常说的“某某对象的成员函数某某对象的成员函数”,是,是从逻辑的角度而言的,而成员函数的存储方式,是从从逻辑的角度而言的,而成员函数的存储方
45、式,是从物理的角度而言的,二者是不矛盾的。物理的角度而言的,二者是不矛盾的。在程序中经常需要访问对象中的成员。访问对象中的在程序中经常需要访问对象中的成员。访问对象中的成员可以有成员可以有3种方法种方法: 通过通过对象名对象名和和成员运算符成员运算符访问对象中的成员访问对象中的成员;通过通过指向对象的指针指向对象的指针访问对象中的成员访问对象中的成员;通过通过对象的引用变量对象的引用变量访问对象中的成员。访问对象中的成员。8.4 对象成员的引用对象成员的引用例如在程序中可以写出以下语句:例如在程序中可以写出以下语句: stud1.num=1001; /假设假设num已定义为公用的整型数据成员已
46、定义为公用的整型数据成员表示将整数表示将整数1001赋给对象赋给对象stud1中的数据成员中的数据成员num。其中其中“.”是成员运算符是成员运算符,用来对成员进行限定,指,用来对成员进行限定,指明所访问的是哪一个对象中的成员。注意不能只写成明所访问的是哪一个对象中的成员。注意不能只写成员名而忽略对象名。员名而忽略对象名。访问对象中成员的一般形式为访问对象中成员的一般形式为对象名对象名.成员名成员名不仅可以在类外引用对象的公用数据成员,而且还可不仅可以在类外引用对象的公用数据成员,而且还可以调用对象的公用成员函数以调用对象的公用成员函数,但同样必须指出对象名,但同样必须指出对象名,如如8.4.
47、1 通过对象名和成员运算符访问对象中的成员通过对象名和成员运算符访问对象中的成员stud1.display( ); /正确,调用对象正确,调用对象stud1的公用成员函数的公用成员函数display( ); /错误,错误,没有指明是哪一个对象的没有指明是哪一个对象的display函数函数由于没有指明对象名,编译时把由于没有指明对象名,编译时把display作为普通函数作为普通函数处理。处理。应该应该注意注意所访问的成员是所访问的成员是公用的公用的(public)还是私有的还是私有的(private)。只能访问只能访问public成员,而不能访问成员,而不能访问private成员,成员,如果已定
48、义如果已定义num为私有数据成员,下面为私有数据成员,下面的语句是错误的:的语句是错误的: stud1.num=10101; /num是私有数据成员,不能被外界引用是私有数据成员,不能被外界引用 在类外只能调用公用的成员函数。在一个类中应当至在类外只能调用公用的成员函数。在一个类中应当至少有一个公用的成员函数,作为少有一个公用的成员函数,作为对外的接口对外的接口,否则就,否则就无法对对象进行任何操作。无法对对象进行任何操作。在第在第7章第章第7.1.5节中介绍了指向结构体变量的指针,节中介绍了指向结构体变量的指针,可以通过指针引用结构体中的成员。用指针访问对象可以通过指针引用结构体中的成员。用
49、指针访问对象中的成员的方法与此类似。如果有以下程序段:中的成员的方法与此类似。如果有以下程序段: class Timepublic: /数据成员是公用的数据成员是公用的int hour;int minute;Time t,*p; /定义对象定义对象t和指针变量和指针变量pp=&t; /使使p指向对象指向对象tcouthour; /输出输出p指向的对象中的成员指向的对象中的成员hour在在p指向指向t的前提下,的前提下,p-hour,(*p).hour和和t.hour三三者等价。者等价。8.4.2 通过指向对象的指针访问对象中的成员通过指向对象的指针访问对象中的成员如果为一个对象定义了一个引用变
50、量,它们是共占同如果为一个对象定义了一个引用变量,它们是共占同一段存储单元的,实际上它们是同一个对象,只是用一段存储单元的,实际上它们是同一个对象,只是用不同的名字表示而已。不同的名字表示而已。因此完全可以通过引用变量来因此完全可以通过引用变量来访问对象中的成员。访问对象中的成员。如果已声明了如果已声明了Time类,并有以下定义语句:类,并有以下定义语句: Time t1; /定义对象定义对象t1Time &t2=t1; /定义定义Time类引用变量类引用变量t2,并使之初始化为并使之初始化为t1coutt2.hour; /输出对象输出对象t1中的成员中的成员hour由于由于t2与与t1共占同
51、一段存储单元共占同一段存储单元(即即t2是是t1的别名的别名),因此因此t2.hour就是就是t1.hour。本章第本章第8.6节的例节的例8.2中的程序中的程序(b),介绍的是引用变量介绍的是引用变量作为形参的情况,读者可以参考。作为形参的情况,读者可以参考。8.4.3 通过对象的引用变量来访问对象中的成员通过对象的引用变量来访问对象中的成员在声明了一个类以后,用户主要是通过调用公用的成在声明了一个类以后,用户主要是通过调用公用的成员函数来实现类提供的功能员函数来实现类提供的功能(例如对数据成员设置值,例如对数据成员设置值,显示数据成员的值,对数据进行加工等显示数据成员的值,对数据进行加工等
52、)。因此,公因此,公用成员函数是用户使用类的公用接口用成员函数是用户使用类的公用接口(public interface),或者说是类的对外接口。或者说是类的对外接口。8.5 类的封装性和信息隐蔽类的封装性和信息隐蔽 8.5.1 公用接口与私有实现的分离公用接口与私有实现的分离当然并不一定要把所有成员函数都指定为当然并不一定要把所有成员函数都指定为public(公用公用)的,但这时这些成员函数就不是公用接口了。的,但这时这些成员函数就不是公用接口了。在类在类外虽然不能直接访问私有数据成员,但可以通过调用外虽然不能直接访问私有数据成员,但可以通过调用公用成员函数来引用甚至修改私有数据成员公用成员函
53、数来引用甚至修改私有数据成员。用户可以调用公用成员函数来实现某些功能,而这些用户可以调用公用成员函数来实现某些功能,而这些功能是在声明类时已指定的,用户可以使用它们而不功能是在声明类时已指定的,用户可以使用它们而不应改变它们。实际上用户往往并不关心这些功能是如应改变它们。实际上用户往往并不关心这些功能是如何实现的细节,而只需知道调用哪个函数会得到什么何实现的细节,而只需知道调用哪个函数会得到什么结果,能实现什么功能即可。结果,能实现什么功能即可。 可以看到:可以看到: 类中被操作的数据是私有的,实现的细类中被操作的数据是私有的,实现的细节对用户是隐蔽的,这种实现称为私有实现节对用户是隐蔽的,这
54、种实现称为私有实现(private implementation)。这种这种“类的公用接口与私有实现的类的公用接口与私有实现的分离分离”形成了信息隐蔽。形成了信息隐蔽。软件工程的一个最基本的原则就是软件工程的一个最基本的原则就是将接口与实现分离将接口与实现分离,信息隐蔽是软件工程中一个非常重要的概念。它的信息隐蔽是软件工程中一个非常重要的概念。它的好好处在于处在于: (1) 如果想修改或扩充类的功能,只需修改本类中有如果想修改或扩充类的功能,只需修改本类中有关的数据成员和与它有关的成员函数,程序中类外的关的数据成员和与它有关的成员函数,程序中类外的部分可以不必修改。部分可以不必修改。(2) 如
55、果在编译时发现类中的数据读写有错,不必检如果在编译时发现类中的数据读写有错,不必检查整个程序,只需检查本类中访问这些数据的少数成查整个程序,只需检查本类中访问这些数据的少数成员函数。员函数。在面向对象的程序开发中,在面向对象的程序开发中,一般做法是将类的声明一般做法是将类的声明(其中包含成员函数的声明其中包含成员函数的声明)放在指定的头文件中,用放在指定的头文件中,用户如果想用该类,只要把有关的头文件包含进来即可,户如果想用该类,只要把有关的头文件包含进来即可,不必在程序中重复书写类的声明,以减少工作量,节不必在程序中重复书写类的声明,以减少工作量,节省篇幅,提高编程的效率。省篇幅,提高编程的
56、效率。由于在头文件中包含了类的声明,因此在程序中就可由于在头文件中包含了类的声明,因此在程序中就可以用该类来定义对象。由于在类体中包含了对成员函以用该类来定义对象。由于在类体中包含了对成员函数的声明,在程序中就可以调用这些对象的公用成员数的声明,在程序中就可以调用这些对象的公用成员函数函数。为了实现上一节所叙述的信息隐蔽,对类成员。为了实现上一节所叙述的信息隐蔽,对类成员函数的定义一般不放在头文件中,而另外放在一个文函数的定义一般不放在头文件中,而另外放在一个文件中。件中。8.5.2 类声明和成员函数定义的分离类声明和成员函数定义的分离例如,可以分别写两个文件:例如,可以分别写两个文件: /s
57、tudent.h (这是头文件,在此文件中进行类的声明这是头文件,在此文件中进行类的声明)class Student /类声明类声明 public:void display( ); /公用成员函数原型声明公用成员函数原型声明private:int num; char name20; char sex; ;/student.cpp /在此文件中进行函数的定义在此文件中进行函数的定义#include #include student.h /不要漏写此行,否则编译通不过不要漏写此行,否则编译通不过void Student display( ) /在类外定义在类外定义display类函数类函数cout
58、num:numendl; coutname:nameendl; coutsex:sexendl; 为了组成一个完整的源程序,还应当有包括主函数的为了组成一个完整的源程序,还应当有包括主函数的源文件:源文件: /main.cpp 主函数模块主函数模块#include #include student.h /将类声明头文件包含进来将类声明头文件包含进来int main( )Student stud; /定义对象定义对象stud.display( ); /执行执行stud对象的对象的display函数函数return 0;这是一个包括这是一个包括3个文件的程序,组成两个文件模块:个文件的程序,组成两
59、个文件模块: 一个是主模块一个是主模块main.cpp,一个是一个是student.cpp。在主模在主模块中又包含头文件块中又包含头文件student.h。在预编译时会将头文件在预编译时会将头文件student.h中的内容取代中的内容取代#include student.h行。行。请注意:请注意: 由于将头文件由于将头文件student.h放在用户当前目录放在用户当前目录中,因此在文件名两侧用双撇号包起来中,因此在文件名两侧用双撇号包起来(student.h)而不用尖括号而不用尖括号(),否则否则编译时会找不到此文件。编译时会找不到此文件。图图8.6。在运行程序时调用在运行程序时调用stud中
60、的中的display函数,输出各数据函数,输出各数据成员的值。成员的值。在实际工作中,并不是将一个类声明做成一个头文件,在实际工作中,并不是将一个类声明做成一个头文件,而是将若干个常用的功能相近的类声明集中在一起,而是将若干个常用的功能相近的类声明集中在一起,形成类库。形成类库。类库有两种:类库有两种:一种是一种是C+编译系统提供的编译系统提供的标准类库标准类库;一种是用户根据自己的需要做成的用户类库,提供给一种是用户根据自己的需要做成的用户类库,提供给自己和自己授权的人使用,这称为自己和自己授权的人使用,这称为自定义类库自定义类库。 类库包括两个组成部分:类库包括两个组成部分: (1)类声明
61、头文件;类声明头文件; (2)已已经过编译的成员函数的定义,它是目标文件。经过编译的成员函数的定义,它是目标文件。类的成员函数在面向对象程序理论中被称为类的成员函数在面向对象程序理论中被称为“方法方法”(method),“方法方法”是指对数据的操作。是指对数据的操作。一个一个“方方法法”对应一种操作。显然,只有被声明为公用的方法对应一种操作。显然,只有被声明为公用的方法(成员函数)才能被对象外界所激活。(成员函数)才能被对象外界所激活。外界是外界是通过发通过发“消息消息”来激活有关方法来激活有关方法的。所谓的。所谓“消息消息”,其实就其实就是一个命令,由程序语句来实现。是一个命令,由程序语句来
62、实现。前面的前面的stud.display( );就是向对象就是向对象stud发出的一个发出的一个“消息消息”,通知它执,通知它执行其中的行其中的display“方法方法”(即(即display函数)。上面这函数)。上面这个语句涉及个语句涉及3个术语:个术语: 对象、方法和消息。对象、方法和消息。stud是对是对象,象,display( )是方法,语句是方法,语句“stud.display( );”是消是消息。息。8.5.3 面向对象程序设计中的几个名词面向对象程序设计中的几个名词例例8.1 最简单的例子。最简单的例子。#include using namespace std;class Ti
63、me /定义定义Time类类public: /数据成员为公用的数据成员为公用的 int hour; int minute; int sec;int main( ) Time t1; /定义定义t1为为Time类对象类对象cint1.hour; /输入设定的时间输入设定的时间cint1.minute;cint1.sec;coutt1.hour:t1.minute:t1.secendl; /输出时间输出时间return 0;8.6 类和对象的简单应用举例类和对象的简单应用举例运行情况如下:运行情况如下: 1232 43 12:32:43注意:注意:(1) 在引用数据成员在引用数据成员hour,mi
64、nute,sec时不要忘记时不要忘记在前面指定对象名。在前面指定对象名。(2) 不要错写为类名,不要错写为类名,如写成如写成Time.hour,Time.minute,Time.sec是不对的。因为类是不对的。因为类是一种抽象的数据类型,并不是一个实体,也不占存是一种抽象的数据类型,并不是一个实体,也不占存储空间,而对象是实际存在的实体,是占存储空间的,储空间,而对象是实际存在的实体,是占存储空间的,其数据成员是有值的,可以被引用的。其数据成员是有值的,可以被引用的。(3) 如果删去主函数的如果删去主函数的3个输入语句,即不向这些数个输入语句,即不向这些数据成员赋值,则它们的值是不可预知的。据
65、成员赋值,则它们的值是不可预知的。例例8.2 引用多个对象的成员。引用多个对象的成员。(1) 程序程序(a)#include using namespace std;class Timepublic:int hour;int minute;int sec;int main( )Time t1; /定义对象定义对象t1cint1.hour; /向向t1的数据成员输入数据的数据成员输入数据cint1.minute;cint1.sec;coutt1.hour:t1.minute:t1.sect2.hour; /向向t2的数据成员输入数据的数据成员输入数据cint2.minute;cint2.sec;
66、coutt2.hour:t2.minute:t2.secendl; /输出输出t2中数据成员的值中数据成员的值return 0;运行情况如下:运行情况如下: 1032 43 10:32:4322 32 43 22:32:43程序是清晰易懂的,但是在主函数中对不同的对象一程序是清晰易懂的,但是在主函数中对不同的对象一一写出有关操作,会使程序冗长。为了解决这个问题,一写出有关操作,会使程序冗长。为了解决这个问题,可以使用函数来进行输入和输出。见程序可以使用函数来进行输入和输出。见程序(b)。(2) 程序程序(b)#include using namespace std;class Timepubl
67、ic:int hour;int minute;int sec;int main( )void set_time(Time&); /函数声明函数声明void show_time(Time&); /函数声明函数声明Time t1; /定义定义t1为为Time类对象类对象set_time(t1); /调用调用set_time函数,向函数,向t1对象中的数据成员输入数据对象中的数据成员输入数据show_time(t1); /调用调用show_time函数,输出函数,输出t1对象中的数据对象中的数据Time t2; /定义定义t2为为Time类对象类对象set_time(t2); /调用调用set_ti
68、me函数,向函数,向t2对象中的数据成员输入数据对象中的数据成员输入数据show_time(t2); /调用调用show_time函数,输出函数,输出t2对象中的数据对象中的数据return 0;void set_time(Time& t) /定义函数定义函数set_time,形参形参t是引用变量是引用变量 cint.hour; /输入设定的时间输入设定的时间 cint.minute; cint.sec;void show_time(Time& t) /定义函数定义函数show_time,形参形参t是引用变量是引用变量 coutt.hour:t.minute:t.secendl; /输出对象中
69、的数据输出对象中的数据运行情况与程序运行情况与程序(a)相同。相同。(3) 程序程序(c)可以对上面的程序作一些修改,数据成员的值不再由可以对上面的程序作一些修改,数据成员的值不再由键盘输入,而在调用函数时由实参给出,并在函数中键盘输入,而在调用函数时由实参给出,并在函数中使用默认参数。使用默认参数。将程序将程序(b)第第8行以下部分改为行以下部分改为int main( ) void set_time(Time&,int hour=0,int minute=0,int sec=0); /函数声明函数声明void show_time(Time&); /函数声明函数声明Time t1;set_ti
70、me(t1,12,23,34); /通过实参传递时、分、秒的值通过实参传递时、分、秒的值show_time(t1);Time t2;set_time(t2); /使用默认的时、分、秒的值使用默认的时、分、秒的值show_time(t2);return 0;void set_time(Time& t,int hour,int minute,int sec) t.hour=hour;t.minute=minute;t.sec=sec;void show_time(Time& t)coutt.hour:t.minute:t.secendl;程序运行时的输出为程序运行时的输出为12:23:34 (t1
71、中的时、分、秒中的时、分、秒)0:0:0 (t2中的时、分、秒中的时、分、秒) 以上两个程序中定义的类都只有数据成员,没有成员以上两个程序中定义的类都只有数据成员,没有成员函数,这显然没有体现出使用类的优越性。在下面的函数,这显然没有体现出使用类的优越性。在下面的例子中,类体中就包含了成员函数。例子中,类体中就包含了成员函数。例例8.3 将例将例8.2的程序改用含成员函数的类来处理。的程序改用含成员函数的类来处理。#include using namespace std;class Timepublic:void set_time( ); /公用成员函数公用成员函数void show_time
72、( ); /公用成员函数公用成员函数 private: /数据成员为私有数据成员为私有int hour;int minute;int sec;int main( )Time t1; /定义对象定义对象t1 t1.set_time( ); /调用对象调用对象t1的成员函数的成员函数set_time,向向t1的数据成员输入数据的数据成员输入数据t1.show_time( ); /调用对象调用对象t1的成员函数的成员函数show_time,输出输出t1的数据成员的值的数据成员的值Time t2; /定义对象定义对象t2t2.set_time( ); /调用对象调用对象t2的成员函数的成员函数set_
73、time,向向t2的数据成员输入数据的数据成员输入数据t2.show_time( ); /调用对象调用对象t2的成员函数的成员函数show_time,输出输出t2的数据成员的值的数据成员的值return 0;void Time set_time( ) /在类外定义在类外定义set_time函数函数 cinhour; cinminute; cinsec;void Time show_time( ) /在类外定义在类外定义show_time函数函数 couthour:minute:secendl;运行情况与例运行情况与例8.2中的程序中的程序(a)相同。相同。注意:注意: (1) 在主函数中调用两
74、个成员函数时,应指明对象名在主函数中调用两个成员函数时,应指明对象名(t1,t2)。表示调用的是哪一个对象的成员函数。表示调用的是哪一个对象的成员函数。(2) 在类外定义函数时,应指明函数的作用域在类外定义函数时,应指明函数的作用域(如如void Time set_time( )。在成员函数引用本对象的数在成员函数引用本对象的数据成员时,只需直接写数据成员名,据成员时,只需直接写数据成员名,这时这时C+系统会系统会把它默认为本对象的数据成员。也可以显式地写出类把它默认为本对象的数据成员。也可以显式地写出类名并使用域运算符。名并使用域运算符。(3) 应注意区分什么场合用域运算符应注意区分什么场合
75、用域运算符“ ”,什么场,什么场合用成员运算符合用成员运算符“.”,不要搞混。,不要搞混。例例8.4 找出一个整型数组中的元素的最大值。找出一个整型数组中的元素的最大值。这个问题可以不用类的方法来解决,现在用类来处理,这个问题可以不用类的方法来解决,现在用类来处理,可以自行比较不同方法的特点。可以自行比较不同方法的特点。#include using namespace std;class Array_max /声明类声明类public: /以下以下3行为成员函数原型声明行为成员函数原型声明void set_value( ); /对数组元素设置值对数组元素设置值void max_value( )
76、; /找出数组中的最大元素找出数组中的最大元素void show_value( ); /输出最大值输出最大值private:int array10; /整型数组整型数组int max; /max用来存放最大值用来存放最大值;void Array_max set_value( ) /成员函数定义,向数组元素输入数值成员函数定义,向数组元素输入数值 int i; for (i=0;iarrayi;void Array_max max_value( ) /成员函数定义,找数组元素中的最大值成员函数定义,找数组元素中的最大值int i;max=array0;for (i=1;imax) max=arr
77、ayi;void Array_max show_value( ) /成员函数定义,输出最大值成员函数定义,输出最大值coutmax=max;int main( )Array_max arrmax; /定义对象定义对象arrmaxarrmax.set_value( ); /调用调用arrmax的的set_value函数,向数组元素输入数值函数,向数组元素输入数值arrmax.max_value( ); /调用调用arrmax的的max_value函数,找出数组元素中的最大函数,找出数组元素中的最大值值arrmax.show_value( ); /调用调用arrmax的的show_value函数,
78、输出数组元素中的最大函数,输出数组元素中的最大值值return 0;运行结果如下:运行结果如下: 12 12 39 -34 17 134 045 -91 76 (输入输入10个元素的值个元素的值)max=134 (输入输入10个元素中的最大值个元素中的最大值)请注意成员函数定义与调用成员函数的关系,定义成请注意成员函数定义与调用成员函数的关系,定义成员函数只是设计了一组操作代码,并未实际执行,只员函数只是设计了一组操作代码,并未实际执行,只有在被调用时才真正地执行这一组操作。有在被调用时才真正地执行这一组操作。可以看出:可以看出: 主函数很简单,语句很少,只是调用有主函数很简单,语句很少,只是调用有关对象的成员函数,去完成相应的操作。在大多数情关对象的成员函数,去完成相应的操作。在大多数情况下,主函数中甚至不出现控制结构况下,主函数中甚至不出现控制结构(判断结构和循判断结构和循环结构环结构),而在成员函数中使用控制结构。在面向对,而在成员函数中使用控制结构。在面向对象的程序设计中,最关键的工作是类的设计。象的程序设计中,最关键的工作是类的设计。所有的所有的数据和对数据的操作都体现在类中。只要把类定义好,数据和对数据的操作都体现在类中。只要把类定义好,编写程序的工作就显得很简单了。编写程序的工作就显得很简单了。