




已阅读5页,还剩61页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第九章第九章 多态性多态性 本章概要: 多态性是面向对象程序设计的第四个基本 特点。从字面上解释,所谓多态性就是“有许 多种形态”。基于这种理解,可以认为函数重 载和运算符重载是多态性的最简单形式。 面向对象程序设计面向对象程序设计 第二版第二版 讲义制作:北京信息工程学院信息与计算科学专业讲义制作:北京信息工程学院信息与计算科学专业0514105141班班 曹硕曹硕 n但是,在面向对象程序设计领域,所谓多态性 通常特指下述机制:派生类对象可以像基类对 象一样使用,同样的消息既可以发送给基类对 象也可以发送给派生类对象。 n也就是说,在类等级的不同层次中可以共享一 个行为的名字,但是不同层次中的类却各自按 自己的需要来实现这个行为。 n简而言之:在不同的类层次中,同一个消息被 不同的对象接收,产生了不同的行为。当一个 对象接收到发送给它的消息时,根据该对象所 属于的类动态选用在该类中定义的实现算法。 n多态性机制不仅增加了面向对象软件系统的灵 活性,进一步减少了冗余信息,而且显著提高 了软件的可重用性和可扩充性。 n本章主要讲述,静态联编与动态联编,虚函数 的声明与使用,虚函数应用实例,纯虚函数, 多态性带来的好处等内容。 本章快速索引本章快速索引 面向对象程序设计面向对象程序设计 第二版第二版 9.1 9.1 静态联编与动态联编静态联编与动态联编 9.2 9.2 虚函数的声明与使用虚函数的声明与使用 9.3 9.3 虚函数应用实例之一虚函数应用实例之一 9.4 9.4 纯虚函数纯虚函数 9.5 9.5 虚函数应用实例之二虚函数应用实例之二 9.6 9.6 多态性带来的好处多态性带来的好处 9.7 9.7 小结小结 9.1 9.1 静态联编与动态联编静态联编与动态联编 n所谓联编(tinding),就是使一个计算机程序的不 同部分彼此关联的过程。 n静态联编在编译阶段完成,因为所有联编过程 都在程序开始运行之前完成,因此静态联编也 叫先前联编或早期联编。 面向对象程序设计面向对象程序设计 第二版第二版 n编译程序在编译时并不确切知道应把发送 到对象的消息和实现消息的哪段具体代码 联编在一起,而是在运行时才能把函数调 用与函数体联系在一起,则称为动态联编 。 9.1.19.1.1静态联编静态联编 对重载函数的调用是在编译阶段完成联编的 ,有下述3种区分重载函数的方法: 根据实参特征来区分。 使用作用域分辨符加以区分。 根据对象的类型来区分。 面向对象程序设计面向对象程序设计 第二版第二版 下面让我们看一个简单程序例子: #include “stdafx.h“ #include “iostream.h“ class Base public: void Who() cout Who(); p = p - Who(); p = p - Who(); first_obj.Who(); second_obj.Who(); 运行输出结果: I am base class I am base class I am base class I am first derived class I am second derived class 9.1.29.1.2动态联编动态联编 n如果随着指针P实际指向的对象不同,使用语 句P-Who( );能够调用不同类中Who的相同 版本,我们就可以用相同的界面P-Who( )访 问函数Who的多个实现版本,从而也就能够 在程序运行时告诉用户,当时指针P实际指向 何类对象。 面向对象程序设计面向对象程序设计 第二版第二版 n函数调用P-Who( )依赖于程序运行时P的值 。虚函数提供的就是这样一种机制。把由指 针调用的成员函数声明为虚函数,则声明为 指向基类对象的指针,可以根据它在程序运 行过程中当时实际指向的对象类型,通过动 态联编调用相应类中的虚函数。 n#include nclass student n npublic: nvoid calct() n ncout Who(); p = p - Who(); p = p - Who(); n运行结果如下: nI am base class nI am first derived class nI am second derived class 9.2 9.2 虚函数的声明与使用虚函数的声明与使用 9.2.19.2.1声明虚函数声明虚函数 声明虚函数的一般格式如下: virtual 函数原型; 必须首先在基类中声明虚函数。 派生类中与基类虚函数原型完全相同的成 员函数,即使在说明时前面没有冠以关键 字virtual也自动成为虚函数。 面向对象程序设计面向对象程序设计 第二版第二版 9.2.19.2.1声明虚函数声明虚函数 只有非静态成员函数可以声明为虚函数。 不允许在派生类中定义与基类虚函数名字及参 数特征都相同,仅仅返回类型不同的成员函数 。 编译时出错。 系统把函数名相同但参数特征不同的函数视为 不同的函数。 通过声明虚函数来使用C+提供的多态性机制 时,派生类应该从它的基类公有派生。 面向对象程序设计面向对象程序设计 第二版第二版 n#include nclass student n npublic: n virtual void calct(int x) n ncout show(); a_p = b_p ; /通过赋值形式,将派生类对象b的指针传递给基类对象指 针 a_p - show();/调用的接口形式不变,仍为“a_p-show()”,但调用的是 b中的show() a_p = c_p ; /通过赋值形式,将派生类对象c的指针传递给基类对象指 针 a_p - show();/调用的接口形式不变,仍为“a_p-show()”,但调用的是 c中的show() 面向对象程序设计面向对象程序设计 第二版第二版 n运行结果: nAAA nBBB nCCC nAAA nBBB nCCC 关于程序的几点说明: 准备实现多态性的方法前面必须加关键字virtual ,这被称为虚函数,是实现多态性的必要条件。 使用多态性时,它的调用接口形式是不变的,关 键是看基类对象的指针指向了哪个对象,就调用 了哪个对象的方法。而这种指向有两种表现形式 :一种是通过实参、形参结合的形式;另一种是 通过赋值语句的形式。 面向对象程序设计面向对象程序设计 第二版第二版 为了实现动态联编,函数中参数类型必须是引用 或者指针类型(如display(A *a);或display(A )。通常用指向第一次定义虚函数的基类对象的 指针来调用虚函数,可以获得运行时的多态性。 (如例中使用“a_p - show();”调用,而没有使用 其他派生类对象指针) 使用普通对象调用虚函数时,系统仍然以 静态联编方式完成对虚函数的调用(如例 中display(A a);),请读者上机实践。 基类与派生类是相对的,因此,并非在任 何情况下都必须首先在类等级的最高层类 内声明虚函数。 9.2.3 9.2.3 动态联编的实现动态联编的实现 nC +语言中的动态联编是通过使用虚函数表 (Virtual Function Table)来实现的,虚函数表也称 为v-表。 n每个类的实例都有一个隐含的指向该类v-表的 指针,当执行诸如a_p - show()这样的语句时 ,系统首先取a_p所实际指向的对象中的v-表指 针,然后调用由这个v-表中指针项所指定的函 数show(),从而实现了对不同类的虚函数的调 用。 面向对象程序设计面向对象程序设计 第二版第二版 9.3 9.3 虚函数应用实例之一虚函数应用实例之一 下面是实现上述要求的程序: #include “stdafx.h“ #include “iostream.h“ class Figure protected: float x, y; public: void Set(float i, float j = 0) x = i; y = j; virtual void ShowArea() ; 面向对象程序设计面向对象程序设计 第二版第二版 class Triangle : public Figure public: void ShowArea() cout Set(12.0, 8.0); p 1 = p 1 - Set(12.0, 8.0); p 2 = p 2 - Set(10.0); for(int i = 0;i ShowArea(); 面向对象程序设计面向对象程序设计 第二版第二版 n运行上列程序,得到下列输出结果: nTriangle with height 12 and base 8 has an area of 48 nSquare with dimension 12 * 8 has an area of 96 nCircle with radius 10 has an area of 314 9.4 9.4 纯虚函数纯虚函数 n纯虚函数是在基类中声明的虚函数,它在声明它的 基类中没有定义,要求任何派生类都必须为该虚函 数定义自己的版本。 n说明纯虚函数的一般格式如下: nvirtual 函数原型 = 0; n例如,为了把Figure类的虚函数ShowArea说明为纯 虚函数,应该像下面那样声明它: nvirtual void ShowArea() = 0; 面向对象程序设计面向对象程序设计 第二版第二版 9.4 9.4 纯虚函数纯虚函数 n关于纯虚函数和抽象类的使用,C+语言 n有以下规定: 抽象类只能作为其他类的基类,不能声明抽 象类的实例。 在从抽象类派生出的新类中,必须重新定 义其父类的每个纯虚函数;或者把这些函数继 续声明为纯虚函数,这样做派生类也就成为抽 象类。 面向对象程序设计面向对象程序设计 第二版第二版 9.4 9.4 纯虚函数纯虚函数 在类等级的上层定义一个或几个抽象类作为基类,而 在下层定义由基类派生出的具体类的情况比较常见, 但是,不允许从具体类派生出抽象类。所谓具体类, 就是不包含纯虚函数的普通类。 在抽象类中也可以定义普通成员函数或虚函数,虽然 不能为抽象类声明对象,但仍然可以通过派生类对象 来调用这些不是纯虚函数的函数。 面向对象程序设计面向对象程序设计 第二版第二版 9.5 9.5 虚函数应用实例之二虚函数应用实例之二 要求设计一个面向对象的程序,以完成下列几项功能: 在显示器荧光屏上指定位置显示指定的图形(点或圆) ,或擦去屏幕上正在显示的某个图形; 放大或缩小屏幕上正在显示的圆; 把某个图形从屏幕上原来的位置移动到指定的新位置 ; 在屏幕上沿指定方向以指定的速度连续拖动指定 的图形。(参考教材请同学上机练习) 面向对象程序设计面向对象程序设计 第二版第二版 #include ”graphics.h” #include ”conio.h” enum Booleanfalse, true; class Location protected : int X; int Y; public : Location(int InitX, int InitY) X = InitX; Y = InitY; int GetX() return X; int GetY() return Y; ; 面向对象程序设计面向对象程序设计 第二版第二版 class Point : public Location protected : Boolean Visible; public : Point(int InitX, int InitY); virtual void Show();/ 虚函数 virtual void Hide();/ 虚函数 virtual void Drag(int DragBy); / 虚函数 Boolean IsVisible() return Visible; void MoveTo(int NewX,int NewY); ; 面向对象程序设计面向对象程序设计 第二版第二版 class Circle : public Point protected : int Radius; public : Circle(int InitX, int InitY, int InitRadius); void Show();/ 虚函数 void Hide();/ 虚函数 void Expand(int ExpandBy); void Contract(int ContractBy); ; Boolean GetDelta(int Boolean Quit; DeltaX = 0; DeltaY = 0; 面向对象程序设计面向对象程序设计 第二版第二版 do KeyChar = getch();/ 读键盘输入 if(KeyChar = 13) return (false); / 回车键结束拖动 if(KeyChar = 0)/ 扩展键码 Quit = true;/ 假设按对了键盘 KeyChar = getch();/ 读剩余的键码 switch(KeyChar) case 72 : DeltaY = -1;break;/ 上箭头键 case 80 : DeltaY = 1;break;/ 下箭头键 case 75 : DeltaX = -1;break;/ 左箭头键 case 77 : DeltaX = 1;break;/ 右箭头键 default : Quit = false;/ 错键 while(!Quit);/ 按错了键可改敲 return (true);/ 箭头键继续拖动 Point Point(int InitX, int InitY) : Location(InitX, InitY) Visible = false;/ 缺省为不可见状态 void Point Show() Visible = true;/ 可见状态 putpixel(X, Y, getcolor();/ 使用缺省颜色 显示 面向对象程序设计面向对象程序设计 第二版第二版 void Point Hide() Visible = false;/ 不可见状态 putpixel(X, Y, getbkcolor();/ 用背景色以擦去这个点 void Point MoveTo(int NewX, int NewY) Hide();/ 使该点成为不可见 X = NewX;/ 修改X,Y坐标到新位置 Y = NewY; Show();/ 在新位置显示该点 void Point :Drag(int DragBy)/ 参数为拖动的步长 int DeltaX, DeltaY; int FigureX, FigureY; Show();/ 显示欲拖动的图形 FigureX = X;/ 图形初始位置 FigureY = Y; while(GetDelta(DeltaX, DeltaY) / 下面是完成拖 动操作的循环语句 FigureX += (DeltaX * DragBy);/ 修改坐标值 FigureY += (DeltaY * DragBy); MoveTo(FigureX,FigureY); Circle :Circle(int InitX, int InitY, int InitRadius) : Point(InitX, InitY) Radius = InitRadius; void Circle :Show() Visible = true; circle(X, Y, Radius);/ 画圆 void Circle :Hide() int TempColor; TempColor = getcolor();/ 保存当前前景色 setcolor(getbkcolor();/ 令背景色为画 圆的颜色 Visible = false; circle(X, Y, Radius);/ 用背景色画圆 setcolor(TempColor);/ 恢复当前前景 色 面向对象程序设计面向对象程序设计 第二版第二版 void Circle : Expand(int ExpandBy) Hide();/ 擦去旧圆 Radius += ExpandBy;/ 扩大半径 if(Radius 0)/ 避免半径值为负数 Radius = 0; Show();/ 显示新圆 void Circle :Contract(int ContractBy) Expand(- ContractBy);/ 用Radius-ContractBy为半径画圆 void main() int graphdriver = DETECT,graphmode; initgraph( Circle MyCircle(100,200,50);/ 说明一个Circle对象 MyCircle.Show();/ 显示它 getch();/ 等待按下任意键 MyCircle.MoveTo(200,250);/ 移动圆 getch(); MyCircle.Expand(50);/ 放大圆 getch(); MyCircle.Contract(75);/ 缩小圆 getch(); MyCircle.Drag(5);/ 拖动圆 closegraph(); 面向对象程序设计面向对象程序设计 第二版第二版 9.69.6多态性带来的好处多态性带来的好处 多态性主要带来以下几点好处: 在类等级的不同层次中,完成相同功能的成员函数 使用相同名字,在程序运行时根据调用该函数的指 针实际指向的对象的类型,动态地决定使用该函数 的哪个版本。 进一步减少了信息冗余。 显著提高了程序的可重用性和可扩充性,因而进一 步提高了程序的可维护性。 面向对象程序设计面向对象程序设计 第二版第二版 9.69.6多态性带来的好处多态性带来的好处 例如,扩充上节的程序,使它增加移动和拖动 弧形对象的功能。为此,仅需像下面那样定义新 的派生类Arc,对原有程序一点也不需改动: 面向对象程序设计面向对象程序设计 第二版第二版 class Arc : public Circle int StartAngle; int EndAngle; public: Arc(int InitX, int InitY, int InitRadius, int InitStartAngle, int InitEnd-Angle) : Circle(InitX, InitY, InitRadius) Start
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 广东广告策划自考试题及答案
- 篮协培训考试题及答案
- 木刻水印雕刻版员数字化技能考核试卷及答案
- 课件无法打开的原因
- 课件旋转平移路径
- 真空制盐工协同作业考核试卷及答案
- 压电石英片烧银焊线工5S管理考核试卷及答案
- 基础强化自考专业(行政管理)试题【历年真题】附答案
- 钢渣处理工质量追溯知识考核试卷及答案
- 2025年康复医学科患者康复方案制定考核试题答案及解析
- 现代设计理论与方法(上)
- EP 中文的课件资料
- 碳纤维材料工程检验批质量验收记录表优质资料
- GB/T 95-2002平垫圈C级
- 现代化工绿色化工课件
- 单孔腹腔镜课程讲义课件
- 人工血管动静脉内瘘术后护理课件
- 普通逻辑ppt课件(完整版)
- 《小学语文课程与教学论》复习题
- DB32∕T 4065-2021 建筑幕墙工程技术标准
- 施工现场环保工作措施
评论
0/150
提交评论