C++程序设计 工业和信息化普通高等教育“十二五”规划教材立项项目 教学课件 ppt 作者 姚琳 C++程序设计第10章

上传人:E**** 文档编号:89345130 上传时间:2019-05-23 格式:PPT 页数:56 大小:274.50KB
返回 下载 相关 举报
C++程序设计 工业和信息化普通高等教育“十二五”规划教材立项项目  教学课件 ppt 作者  姚琳 C++程序设计第10章_第1页
第1页 / 共56页
C++程序设计 工业和信息化普通高等教育“十二五”规划教材立项项目  教学课件 ppt 作者  姚琳 C++程序设计第10章_第2页
第2页 / 共56页
C++程序设计 工业和信息化普通高等教育“十二五”规划教材立项项目  教学课件 ppt 作者  姚琳 C++程序设计第10章_第3页
第3页 / 共56页
C++程序设计 工业和信息化普通高等教育“十二五”规划教材立项项目  教学课件 ppt 作者  姚琳 C++程序设计第10章_第4页
第4页 / 共56页
C++程序设计 工业和信息化普通高等教育“十二五”规划教材立项项目  教学课件 ppt 作者  姚琳 C++程序设计第10章_第5页
第5页 / 共56页
点击查看更多>>
资源描述

《C++程序设计 工业和信息化普通高等教育“十二五”规划教材立项项目 教学课件 ppt 作者 姚琳 C++程序设计第10章》由会员分享,可在线阅读,更多相关《C++程序设计 工业和信息化普通高等教育“十二五”规划教材立项项目 教学课件 ppt 作者 姚琳 C++程序设计第10章(56页珍藏版)》请在金锄头文库上搜索。

1、2019/5/23,北京科技大学,1,C+程序设计,第10章 多态性与虚函数,北京科技大学 信息基础科学系,-2-,多态性(Polymorphism)是面向对象程序设计的主要特征之一。多态性对于软件功能的扩展和软件重用都有重要的作用。是学习面向对象程序设计必须要掌握的主要内容之一。,-3-,第十章 多态性与虚函数,主要内容: 多态性的概念 继承中的静态联编 虚函数和运行时的多态 纯虚函数和抽象类,2019/5/23,北京科技大学,4,10.1 多态性的概念,-5-,面向对象程序设计中多态的表现,总的来说,不同对象对于相同的消息有不同的响应,就是面向对象程序设计中的多态性。 具体在程序中,多态性

2、有两种表现的方式: 同一个对象调用名字相同、但是参数不同的函数,表现出不同的行为。在同一个类中定义的重载函数的调用,属于这种情况。 不同的对象调用名字和参数都相同的函数,表现出不同的行为。在派生类的应用中,经常会看到这样的调用。,-6-,面向对象程序设计中多态的表现,面向对象程序设计中多态性表现为以下几种形式: 重载多态:通过调用相同名字的函数,表现出不同的行为。运算符重载也是一种重载多态。 运行多态:通过基类的指针,调用不同派生类的同名函数,表现出不同的行为。许多面向对象程序设计的书籍中所说的多态性,就是这种多态。,Pt-Draw();,-7-,多态的实现:联编,一个具有多态性的程序语句(如

3、Pt-Draw();),在执行的时候,必须确定究竟是调用哪一个函数。也就是说,在执行的时候调用哪个函数是唯一地确定的。确定具有多态性的语句究竟调用哪个函数的过程称为联编(Binding),有的资料也翻译成“绑定”。,-8-,多态的实现:联编,联编有两种方式:静态联编和动态联编 在源程序编译的时候就能确定具有多态性的语句调用哪个函数,称为静态联编 对于重载函数的调用就是在编译的时候确定具体调用哪个函数,所以是属于静态联编 用静态联编实现的多态,也称为编译时的多态,-9-,多态的实现:联编,动态联编则是必须在程序运行时,才能够确定具有多态性的语句究竟调用哪个函数 用动态联编实现的多态,也称为运行时

4、的多态,2019/5/23,北京科技大学,10,11.2 继承中的静态联编,-11-,派生类对象调用同名函数,在派生类中可以定义和基类中同名的成员函数。这是对基类进行改造,为派生类增加新的行为的一种常用的方法 通过不同的派生类的对象,调用这些同名的成员函数,实现不同的操作,也是多态性的一种表现 在程序编译的时候,就可以确定派生类对象具体调用哪个同名的成员函数。这是通过静态联编实现的多态,-12-,例10-1 定义Circle类和Rectangle类为Shape类的派生类,通过Circle类和Rectangle类的对象调用重载函数getArea()显示对象的面积。 / 例10-1: shape.

5、h class Shape public: double getArea() const; void print() const; ; / Shape类定义结束,-13-,class Circle : public Shape public: Circle( int = 0, int = 0, double = 0.0 ); double getArea() const; / 返回面积 void print() const; / 输出Circle 类对象 private: int x,y; / 圆心座标 double radius; / 圆半径 ; / 派生类Circle定义结束 class

6、Rectangle : public Shape public: Rectangle( int = 0, int = 0); / 构造函数 double getArea() const; / 返回面积 void print() const; / 输出Rectangle类对象 private: int a,b; / 矩形的长和宽 ; / 派生类Rectangle定义结束,-14-,/ 例10-1: shape.cpp #include using namespace std; #include “shape.h“ double Shape:getArea() const cout“基类的getA

7、rea函数,面积是 “; return 0.0; / Shape类getArea函数的定义 void Shape:print() const cout“Base class Object“endl; /Shape类print函数定义,-15-,Circle:Circle( int xValue, int yValue, double radiusValue ) x=xValue; y=yValue; radius= radiusValue ; /Circle类构造函数 double Circle:getArea() const cout“Circle类的getArea函数,面积是 “; ret

8、urn 3.14159 * radius * radius; /Circle类getArea函数定义 void Circle:print() const cout “center is “; cout“x=“x“ y=“y; cout “; radius is “ radiusendl; /Circle类print函数定义,-16-,Rectangle:Rectangle( int aValue, int bValue ) a=aValue; b=bValue; / Rectangle类构造函数 double Rectangle:getArea() const cout“Rectangle类的

9、getArea函数,面积是 “; return a * b; / Rectangle类getArea函数定义 void Rectangle:print() const cout “hight is “a; cout“width is“bendl; / Rectangle类print函数定义,-17-,/ 例10-1: 10_1.cpp #include using std:cout; using std:endl; #include “shape.h“ / 包含头文件 void main() Circle circle( 22, 8, 3.5 ); / 创建Circle类对象 Rectangl

10、e rectangle( 10, 10 ); / 创建Rectangle类对象 cout “调用的是 “; coutcircle.getArea() endl; / 静态联编 cout “调用的是“; coutrectangle.getArea() endl; / 静态联编 ,运行结果: 调用的是Circle类的getarea函数,面积是38.4845 调用的是Ractangle类的getarea函数,面积是100,-18-,派生类对象调用同名函数,对于派生类对象调用成员函数,可以有以下的结论: 派生类对象可以直接调用本类中与基类成员函数同名的函数,不存在二义性; 在编译时就能确定对象将调用哪

11、个函数,属于静态联编,不属于运行时的多态。,-19-,通过基类指针调用同名函数,从继承的角度来看,派生类对象是基类对象的一个具体的特例。或者说,派生类对象是某一种特定类型的基类对象。 例如,Circle类是Shape类的公有继承,“圆”是“图形”的一种特例。或者说,圆是一种特定的图形,具有图形的基本特征。 但是,这种关系不是可逆的。不可以说基类的对象具有派生类对象的特征,基类对象也不是派生类对象的一个特例。,-20-,通过基类指针调用同名函数,当派生类是基类的公有继承时,在关于基类对象和派生类对象的操作上,可以允许以下操作: 派生类对象可以赋值给基类对象; 派生类对象的地址可以赋值给基类对象的

12、指针。或者说,可以用派生类对象的地址初始化基类对象的指针; 可以将基类对象的引用,定义为派生类对象的别名,或者说,用派生类对象初始化基类的引用。 通过派生类对象的地址初始化的基类对象的指针,可以访问基类的公有成员,也可以访问派生类中和基类成员函数同名的函数。,Base b; Deriver d; b=d; Base *pt=,-21-,通过基类指针调用同名函数,以下这些操作是不可以进行的: 不可以将基类对象赋值给派生类对象; 不可以用基类对象的地址初始化派生类对象的指针; 不可以将派生类对象的引用定义为基类对象的别名; 不可以通过用派生类对象初始化的基类对象的指针,访问派生类新增加的和基类公有

13、成员不重名的公有成员。,-22-,例10-2 在例10-1所定义的类的基础上,观察通过派生类对象地址初始化的基类对象的指针访问getArea函数的结果 #include using namespace std; #include “shape.h“ void main() Shape *shape_ptr; Circle circle( 22, 8, 3.5 ); Rectangle rectangle( 10, 10 ); shape_ptr = / 静态联编 ,circle 对象初始化shape_ptr指针访问的getArea函数是 基类的getArea函数,面积是 0 rectangle

14、 对象初始化shape_ptr指针访问的getArea函数是 基类的getArea函数,面积是 0,-23-,通过基类指针调用同名函数,程序运行结果表明: 确实可以用派生类对象的地址初始化基类对象的指针 通过用派生类对象地址初始化的基类对象指针,只能调用基类的公有成员函数。在以上例子中,就是调用基类的getArea函数,而不是派生类的getArea函数 这种调用关系的确定,也是在编译的过程中完成的,属于静态联编,而不属于运行时的多态,2019/5/23,北京科技大学,24,10.3 虚函数和运行时的多态,怎样使语句:shape_ptr-getArea() 实现运行时的多态!,-25-,虚函数和

15、运行时的多态,通过指向基类的指针访问基类和派生类的同名函数,是实现运行时的多态的必要条件,但不是全部条件 除此以外,还必须将基类中的同名函数定义为虚函数,-26-,虚函数,所谓虚函数就是在基类的该函数声明前加上关键字virtual,并由派生类重新定义的函数 虚函数可以在基类的定义中声明函数原型的时说明,格式如下: virtual 返回值类型 函数名(参数表); 在函数原型中声明函数是虚函数后,具体定义这个函数时就不需要再说明它是虚函数了 如果在基类中直接定义同名函数,定义虚函数的格式是: virtual 返回值类型 函数名(参数表) 函数体 ,-27-,虚函数,基类中的同名函数声明或定义为虚函

16、数后,派生类的同名函数无论是不是用virtual来说明,都将自动地成为虚函数。从程序可读性考虑,一般都会在这些函数的声明或定义时,用virtual来加以说明。 只要对例10-2中的头文件稍加修改,也就是将基类和派生类中的getArea函数都声明为虚函数,再重新编译和运行程序,就可以得到运行时的多态的效果。,-28-,例10-3 将例10-2进行修改,使得程序具有运行时的多态的效果。 / 例10-3: shape.h class Shape public: virtual double getArea() const; void print() const; ; / Shape类定义结束,-29-,class Circle

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号