收藏 分享(赏)

第2章对象、类和派生.ppt

上传人:tangtianxu1 文档编号:3503104 上传时间:2018-11-07 格式:PPT 页数:90 大小:156KB
下载 相关 举报
第2章对象、类和派生.ppt_第1页
第1页 / 共90页
第2章对象、类和派生.ppt_第2页
第2页 / 共90页
第2章对象、类和派生.ppt_第3页
第3页 / 共90页
第2章对象、类和派生.ppt_第4页
第4页 / 共90页
第2章对象、类和派生.ppt_第5页
第5页 / 共90页
点击查看更多>>
资源描述

1、1,第2 章 对象、 类和派生,概述 类和对象 构造函数和析构函数const对象和const成员函数 实例 : 有理数类继承: 基类和派生类 7.实例 : 类point、circle和cylinder,2,概述,对象:问题对象行动或思考时作为目标的人或事物.通过对象思考问题.软件对象(模拟问题对象)数据(表示属性)操作(对象的行为),3,2. 类:对象划分成类.一类对象的描述.数据成员 成员函数对象通过类生成 程序设计以函数为单位;以类为单位.程序结构:类结构.,封装,4,用面向对象的程序语言进行程序设计,一个基本工作就是定义程序中所需要的各种对象。采用的方式是先定义对象的类,然后用这些类生成

2、程序中要使用的对象。把类看成类型, 对象看成变量,用类型声名变量;用类声名对象。类型 变量名类 对象,5,2. 类和对象,class 类名 private:私有的数据和成员函数;public:公有的数据和成员函数;类是对象的抽象, 是定义对象的一种抽象数据类型;而对象是类的具体实例。,class stud private:int num;char name10;char sex;public:void display( ) cout“num”numendl; cout“name”nameendl;cout“sex”sexendl; stud student1, student2 ;,7,访问权

3、限:类是一个程序范围,在一个类内, private下的成员,仅能被类内的成员函数访问.public下的成员,能被类内的成员函数和外部的函数访问.访问表示法: 对象名.成员例: student1.display(),8,public:成员1; .成员n,不可见部分: private:成员1; .成员m public:成员函数的实现,用户1可见部分,用户2,用户i,9,构造函数(constructor)作用: 建立对象时初始化;建立对象时自动执行;表示方法: 同类名 和 析构函数(destructor)作用: 对象灭亡时做善后工作;对象灭亡时系统自动执行它.表示方法: 类名( ),10,class

4、 stud private:int num;char name10;char sex;public:stud( ) num=10010; sex=f ;name=strcpy(name,”Wang_Li”:void display( ) cout“num”numendl; cout“name”nameendl;cout“sex”sexendl; stud student1;,11,构造函数可定义如下:stud ( int n, char namee , char s ) num=n; strcpy(name, namee);sex=s; stud student1( 10010, “Wang_

5、Li”, f ); stud student21( 10011, “Zhang_Fun”, m );,12,构造函数可以重载:stud ( ) num=10010; sex= f ;strcpy(name, “Wang_Li”);stud ( int n, char namee , char s ) num=n; strcpy(name, namee);sex=s; stud student1( ); stud student21( 10011, “Zhang_Fun”, m );,13,例 15.2 含有析构函数 #include #include class stud private:in

6、t num;char name10;char sex;public:stud (int n, char namee , char s ) num=n; sex=s;strcpy(name,namee);stud( ) ,14,void display( ) cout“num”numendl; cout“name”nameendl;cout“sex”sexendl; Void main( ) stud student1(10010, “Wang_Li”,f ),student2(10011, “Zhang_Fun”, m);student1.display( );student2.display

7、( );,15,例 15.3 在类的外面定义成员函数 #include #include class stud private:int num;char name10;char sex;public:stud (int n, char namee , char s );stud( ) ; display( );,16,stud:stud( int n, char namee , char s) num=n; strcpy(name, namee); sex=s; stud:stud( ) void stud: display( ) cout“num”numendl; cout“name”nam

8、eendl; cout“sex”sexendl;,17,void main( ) stud student1(10010, “Wang_Li”,f ),student2(10011, “Zhang_Fun”, m);student1.display( );student2.display( );,18,用面向对象的术语,访问一个成员函数的过程被称为向对象“发送一个消息”,对象之间通过这种消息发送的方式互相传递信息。 成员函数也称为方法.,19,const对象与const成员函数用const指定对象不能修改,且若修改会产生语法错误. 例,const time noon(12, 0, 0) ;仅声

9、明为const 的成员函数能调用(作为消息发送给)const对象. 隐含:* const 成员函数不能修改(const对象的)数据成员;* const 成员函数不能调用同一类实例的非 const 成员函数 ;* const对象不能调用非const 成员函数 ;,20,下面是有理数类的例子,21,类的界面描述和实现我们以数学中有理数作为例子,详细介绍C+语言中提供的各种支持构造类和对象的机制。,22,class rational public:rational( );rational(int);rational(int,int);rational(const rational ,23,通常把一个

10、类的界面定义和类实现的程序代码分放在两个文件里:界面定义文件,它给出类的定义,其中说明了类的名字、类中各个数据成分的名字和类型、类中各有关操作的名字及操作的参数类型,等等。实现文件,在这个文件里给出各操作的具体程序代码。,24,类的界面描述本身通常分成两个部分: 用关键字public引出的一段(称为公共部分)描述的是类的界面,在这里说明的各种成分在类外部都可以(直接) 引用, 而由另一个关键字private开始的一段(私有部分)里定义的各种操作和数据成分则完全是内部的,这些成分用于类的实现,在类外面根本看不见,也就完全不能使用。,25,2.3.1 类的数据域类定义里通常说明一些存储数据值的域。

11、在程序执行中,这些数据域的值刻画了对象(类的实例)的内部状态。在有理数类的定义里有两个数据域,它们位于定义的最后部分,这两个域都是整数类型的,名字分别是numerator和denominator,用于表示有理数的分子和分母。,26,2.3.2 对象的行为成员函数为了实现有理数类,能够表示有理数和说明有理数变量只是问题的一个方面,另一个更重要的方面是需要提供一批能够对有理数进行操作的函数。,27,对有理数的最基本操作是访问其分子和分母,在有理数类里提供了一对函数(num和den)来实现这两个访问操作。由于一个类可以产生多个实例,因此,在使用函数时必须说明被作用的对象是哪一个实例。C+语言提供的写

12、法是首先指明被操作的对象本身(例如写出一个变量名),后面写一个圆点,随后再给出对这个对象使用的函数。,28,假定left和right是两个有理数变量,下面的表达式将计算出它们的和的分子(值):left.num( )*right.den( )+right.num( )*left.dem( ),29,C+语言里,为类实例的各种行为定义的函数被称为是类的“成员函数”。为了完成有理数类的定义,我们还必须为各个成员函数提供实际实现的代码。在成员函数的头部除了写出函数本身名字外,在它之前还需要给出它所属的类的名字,其具体表示方式是用符号“:”把类名和函数名连接起来。,30,int rational:num

13、( )const return numerator; int rational:den( ) const return denominator; ,31,函数的参数表后面写着关键字const,说明该函数的执行不会改变被它作用的实例本身。例如num和den函数的执行不会对被作用的有理数的值产生任何影响。这种函数被称为“常数函数”。,32,2.3.3 运算符作为成员函数如果一个运算符需要直接使用类的私有成分,那么它就应该定义为类的成员函数。类2.1描述了与有理数有关的各种赋值函数的原型,它们都被定义为类的成员函数,33,在定义二元运算符成员函数时,作为定义主体的类实例本身就是运算符左边的那个运算对

14、象,因此它不必再进行说明。这样,我们在函数定义的首部只需要说明运算符右边的那个运算对象。下面是赋值运算和递加赋值运算的定义:,34,void rational:operator=(const rational ,35,void rational:operator+=(const rational /对结果做正规化 ,36,当我们想为一个运算符定义重载时,必须用关键字operator作为运算符号的先导,这是语言的规定。,37,由于通过加法运算得到的结果可能不再是最简分数,因此在得到了结果后还需要对其进行正规化,约去分子分母的公约数。有理数正规化操作用类的成员函数normalize完成。在类定义中

15、,normalize被说明为一个“私有”成员函数。,38,还有一个值得注意的问题:如果在一个成员函数的实现程序里调用本类的另一个成员函数,就不需要再说明函数的接受者,这时该函数的接受者自动地被认为是当前实例。,39,void rational:normalize( ) /先 将符号存到sign中,然后 约去公因子int sign=1; / sign为1表示正,-1表示负if (numerator0)sign=-1;numerator=-numerator;if (denominator0)sign=-sign;denominator=-denominator;assert(denominato

16、r!=0); /分母为零int d=gcd(numerator,denominator); /求出最大公约数numerator=sign*(numerator/d);denominator=denominator/d; ,40,normalize函数首先检查分子分母的当前值,以确定计算结果的符号。它把这个符号存放在变量sign中,并将numerator和denominator都置成正数。下一步是调用函数gcd求出两个正数的最大公约数,然后将分子、分母分别设置为最终的值,41,在normalize函数的定义里使用了assert函数。assert是C+运行库提供的一个标准函数,它以一个逻辑条件作为

17、参数,在运行当中,这个逻辑条件不成立时,assert产生一个消息并终止程序运行。如果在本函数的定义里不进行检查,在出现分母为零时就会产生一个“除零”错误(运行错误)。使用了assert函数虽然不能避免实际错误的出现,但程序可以更准确地指明错误发生的位置。,42,2.3.4 用构造函数进行实例的初始化构造函数直接采用类名作为函数名,定义构造函数的语法形式与定义普通成员函数类似,不同点就是它的名字已经确定了(直接用类的名字),且这种函数定义时不说明返回值类型。构造函数名也可以重载,只要给出的不同函数定义在参数个数或类型方面互相不完全相同即可。,43,构造函数在变量定义语句中被隐含地调用,这时可以采

18、用与函数调用类似的语法形式,但是要把被说明的变量名放在函数名的位置。rational a(2);/把变量a初始化为2/1rational b(2,3);/ 把变量b初始化为2/3rational c(3,6);/把变量c初始化为1/2,44,对于只有一个参数的构造函数,函数调用还可以写成类似赋值运算的形式,这样写出的东西就像C+(或C)语言里对普通变量做初始化的形式一样。例如上面的第一个例子可以等价地写为:rational a=2;,45,1. 构造函数的实现一方面,构造函数没有返回值,因而不写返回值类型;另一方面,构造函数头部的最后还可以写一系列的初始式。下面这个构造函数由一个整数参数出发,

19、构造出一个有理数:rational:rational(int num):numerator(num)denominator=1;,46,这个定义中采用了一个初始式:numerator(num),表示用参数num给有理数的numerator数据域确定值。一般的情况是,在参数表后面可以写一个冒号,冒号后面可以写出一系列以逗号分隔的类似函数调用的表达式,这些表达式就称为“初始式”。每个初始式包括一个数据域名,后随由括号括起的一个初始化表达式。初始式的作用是用表达式对类实例的数据域进行初始化。,47,对于带两个整型参数的构造函数,应先用参数对两个数据成分进行初始化,然后对有理数进行正规化,以保证它具有

20、规范的值。在我们的定义里,保证了每一个有理数的值都是正规的:rational:rational(int num,int den):numerator(num),denominator(den)normalize( );,48,2.复制构造函数在类1.2中最后一个构造函数不但在变量定义进行初始化时可能使用,在把有理数值由一个地方复制到另一个地方时也要使用。,49,复制构造函数只有一个同类型的引用参数,这个参数应该定义为常量引用参数,以保证该函数在任何情况下都能正常使用:rational:rational(const rational &value):numerator(value.numerat

21、or),denominator(value.denominator)/ 空函数体,50,3. 类型转换过程中构造函数的作用构造函数不仅在变量说明语句执行时被隐含地自动调用,还被隐含地用于实现类型之间的转换。考虑下面的语句序列:rational x,y;y=x+3;,51,2.4 普通运算符和普通函数,52,2.4.1 普通运算符C+语言对运算符号的处理方式与一般函数基本一样,只是运算符号在实际应用时采用中缀形式书写。C+语言里所有的函数名(包括运算符)都可以由用户自己定义新的重载,唯一的限制是:对已有名字的新定义不能与它原有的定义混淆,这实际上要求新函数定义的参数的个数、类型不能与原有的某个定

22、义完全一样。,53,下面给出有理数加法运算的实现: rational operator +(const rational ,54,上面函数定义的参数表里用了&符号,表示该参数是个引用参数。C+语言里扩充了新的引用参数机制,采用引用参数在许多情况下都能够提高工作效率。写在上面参数表里用const把参数说明为常量参数,这表示参数值在函数执行过程中不会被改变。,55,对于新定义的类型,运算符的实现通常也被放在类的实现文件里,在类的界面描述文件里应该包括这些运算的描述。下面是几个有理数运算的原型说明:,56,rational operator +(const rational ,57,下面给出的是“大

23、于或等于”运算的定义:int operator =(const rational ,58,2.4.2 普通函数普通函数的定义方式与C语言中的函数定义在 形式上完全一样,函数实现里不能使用类的私有成分,普通函数的名字也可以重载。,59,2.4.3 对象的输入和输出,C+语言是C的扩充,在C+程序中也可以采用C的输出方式。例如: printf(“%d,%d,%d,%dn”,m,n,k,(m+n+k)/3 );上述方法有一个问题:在函数printf被定义之后,它能够处理的格式描述符也就固定下来了。,60,要解决输出函数功能可扩充问题,C+语言提出的方法是对运算符进行重载,为此,C+ 语言中引进了一种

24、新的数据类型流,对于输出提供的流是ostream(输出流类),对于输入提供的流是istream(输入流类)。流是一种可以向文件输出(或从文件输入)数据的机制。,61,C+中用来表示输出的运算符是,用它的重载描述将数据送入流的操作。当运算符右边的参数是一个字符时,该字符的值就被送到与流关联的文件里。,62,在C+语言的标准输入输出库里定义了一个全局变量cout,它表示“标准输出流”,这个流被关联于系统的标准输出设备(通常是终端显示器)。这样,用下面一个语句就能够实现与前面例子同样的输出。 coutm,n,k,(m+n+k)/3;,63,对于有理数的输出,我们可以写出如下定义: ostream ,

25、64,对于输入有一个istream(输入流)类。与cout相对应的,C+语言的标准输入输出库提供了一个标准输入流cin,它通常被连接到系统的标准输入设备(一般连接到终端的键盘)。在输入过程中,流输入操作将忽略实际输入序列中的各种空白符号(包括空格符、制表符、换行符等)。如果intv是整型变量,下面语句将把一个整型值赋给这个变量:cinintv;,65,用构造的输入语句可以直接用作条件语句或循环语句的条件表达式,当输入中遇到文件结束时,表达式将返回逻辑“假”。与输出的情况相同,用户也可以方便地为自己的类型定义输入运算符的重载。程序1.2是为有理数输入而写的定义。,66,istream / 返回流

26、 in ,67,有理数类例子到此结束,68,继承: 基类和派生类,软件复用,通过已有的类建立新类 对象分类常出现下面的层次谱系,图形,二维图形,三维图形,圆,方形,三角形,球,六面体,圆柱,69,基类,数据成员 成员函数,继承部分 新定义部分,派生类,继承,派生,70,定义派生类的一般形式: class 派生类名: 引用权限 基类名派生类新增加的数据成员派生类新增加的成员函数 引用权限: private /* 缺省 */publicprotected从基类继承来的成员的引用权限.,71,例 15.4 通过继承建立派生类 #include #include class stud private:

27、int num;char name10;char sex;public:stud (int n, char namee , char s );stud( ) ; display( );/* 成员函数的定义*/,72,class student : public stud private:int age ;char addr30;public:void display_1 ( ) cout“age:”ageendl;cout“address:”addrendl;student student1 ;,73,14.3 公用派生类(一个类的)友员函数和友员类friend 函数名friend 类名友员函

28、数和友员类的成员函数可以访问该类中的private成员.protected成员protected介于private和public之间.基类的protected成员只能被基类的成员和友员以及派生类的成员和友员访问.,74,公用派生类,基类 private 成员 protected 成员 public 成员,派生类不可访问protected 成员public 成员,75,例 15.4 通过继承建立公用派生类 #include #include class stud private:int num;char name10;char sex;public:stud (int n, char namee

29、 , char s );stud( ) ; display( );/* 成员函数的定义*/,76,class student : public stud private:int age ;char addr30;public:void show ( ) cout“num:”numendl;cout“name:”nameendl;cout“sex:”sexendl;cout“age:”ageendl;cout“address:”addrendl; ,/*error*/,77,class student : public stud private:int age ;char addr30;publ

30、ic:void show ( ) display( );cout“age:”ageendl;cout“address:”addrendl; ,78,私有派生类,基类 private 成员 protected 成员 public 成员,派生类不可访问private 成员private 成员,79,例 15.4 通过继承建立私有派生类 #include #include class stud private:int num;char name10;char sex;public:stud (int n, char namee , char s );stud( ) ; display( );/* 成

31、员函数的定义*/,80,class student : private stud private:int age ;char addr30;public:void show ( ) display( ); /* 访问私有成员*/cout“age:”ageendl;cout“address:”addrendl; ,81,Protected继承,基类 private 成员 protected 成员 public 成员,派生类不可访问protected 成员protected 成员,82,15.4.6 派生类的构造函数在派生类中只执行派生类的构造函数.设计的派生类构造函数应该调用基类的构造函数.例

32、15.7 派生类的构造函数,83,#include#includeclass stud protected:int num;char name10;char sex;public:stud (int n, char namee , char s );stud( ) ; display( ); ;/* 成员函数的定义*/,84,class student : private stud private:int age ;char addr30;public:student (int n,char nam , char s, int a, char ad ):stud(n, nam, s ) age

33、=a; strcopy(addr,ad);void show ( ) display( ); /* 访问私有成员*/cout“age:”ageendl;cout“address:”addrendl; student( ) ;,85,实例: 类point、circle和cylinder,point,circle,cylinder,86,#define POINT_Hclass point friend ostream ,87,#includeclass circle: public point friend ostream /* 成员函数的定义*/,88,#includeclass cylinder: public circle friend ostream /*成员函数定义*/,89,int main( ) cylinder cyl(5.7, 2.5, 12, 23 ) ;cyl.setheight(10) ;cyl.setradius(4.25) ;cyl.setpoint(2, 2) ;point ,90,C+ 大学教程(第二版) The Complete C+ Training CourseSecond EditionHarvey M.DeitelPaul James Deitel邱仲潘 等译冯 平 审校电子工业出版社,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 实用文档 > 往来文书

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报