面向对象程序设计》多态.ppt_第1页
面向对象程序设计》多态.ppt_第2页
面向对象程序设计》多态.ppt_第3页
面向对象程序设计》多态.ppt_第4页
面向对象程序设计》多态.ppt_第5页
已阅读5页,还剩40页未读 继续免费阅读

下载本文档

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

文档简介

*北京科技大学计算机系1 C+大学基础教程 第10章 多态性 北京科技大学 计算机系 * 北京科技大学计算机系-2- 第十一章 多态性 11.1 多态性的概念 11.2 继承中的静态联编 11.3 虚函数和运行时的多态 11.4 纯虚函数和抽象类 * 北京科技大学计算机系-3- 多态性的概念 多态性是面向对象程序设计的重要特征之一 。 多态性是指发出同样的消息被不同类型的对 象接收时导致不同的行为。 擦 地板 窗户 脸 采用不同的工具,不同 的方式。在c+中可以用 相同的函数名,不同的 函数操作来实现 函数重载: 函数名相同,但是函数 的参数个数或者参数类 型不同,或者const标识 * 北京科技大学计算机系-4- 11.1.1面向对象程序设计中多态的表现 总的来说,不同对象对于相同的消息有不同的响 应,就是面向对象程序设计中的多态性。 具体在程序中,多态性有两种表现的方式: n同一个对象调用名字相同、但是参数不同的函数,表 现出不同的行为。重载多态 在同一个类中定义的重载函数的调用。 n不同的对象调用名字和参数都相同的函数,表现出不 同的行为。-运行多态 在派生类中重复定义 同名覆盖:使用派生类的定义 作用域符的使用:使用基类的定义 * 北京科技大学计算机系-5- 继承和派生中的多态 class A public: void f( ); ; class C: public A public: void f( ); void f(int x ); ; 如果声明:C c1; 则 c1.f( ); c1.f(int x ); c1.A:f() * 北京科技大学计算机系-6- 11.1.1面向对象程序设计中多态的表现 面向对象程序设计中多态性表现为以下几种形 式: n重载多态:通过调用相同名字的函数,表现出不同 的行为。 n运行多态:通过基类的指针或引用,调用不同派生 类的同名函数,表现出不同的行为。许多面向对象 程序设计的书籍中所说的多态性,就是这种多态。 n模板多态,也称为参数多态:通过一个模板,得到 不同的函数或不同的类。这些函数或者类具有不同 的特性和不同的行为。 * 北京科技大学计算机系-7- 多态性的概念 例1 int max(int a, int b)return ab?a:b; int max(int a, int b, int c) return (int t=(ab?a:b)c?t:c; float max(float a, float b) void main() int a,b,f; float c,d; max(a,b); max(c,d); 在编译的时候,确定 调用的是哪个max, 静态联编; 函数重载 * 北京科技大学计算机系-8- 继承和派生中的多态 class A public: void f( ); ; class C: public A public: void f( ); void f(int x ) ; ; 如果声明:C c1; 则 c1.f( ); c1.f(int x ); c1.A:f() 静态联编; * 北京科技大学计算机系-9- 派生类对象调用同名函数 对于派生类对象调用成员函数,可以有以下的 结论: n派生类对象可以直接调用本类中与基类成员函数同 名的函数,不存在二义性; n在编译时就能确定对象将调用哪个函数,属于静态 联编,不属于运行时的多态。 * 北京科技大学计算机系-10- 赋值兼容原则 一个公有派生类的对象在使用上可以被当作基 类的对象,反之则禁止。具体表现在: derived d; base b; n派生类的对象可以被赋值给基类对象。 b=d; 派生类的对象可以初始化基类的引用。 base n指向基类的指针也可以指向派生类。 base *pb= * 北京科技大学计算机系-11- 赋值兼容规则举例 - 多态是否具有动态性 #include class B0/基类B0声明 public: void display( ) coutdisplay( );/“对象指针-成员名“ 定义了类族 定义了基类的 对象指针 * 北京科技大学计算机系-13- void main( )/主函数 B0 b0;/声明B0类对象 B1 b1;/声明B1类对象 D1 d1;/声明D1类对象 B0 *p;/声明B0类指针 p=/B0类指针指向B0类对象 fun(p); p=/B0类指针指向B1类对象 fun(p); p=/B0类指针指向D1类对象 fun(p); B0:display( ) B0:display( ) B0:display( ) * 北京科技大学计算机系-14- 概念复习 根据赋值兼容规则,下列哪一个陈述是正确的?【 】 A.公有派生类的对象可以赋值给基类的对象。 B.任何派生类的对象可以赋值给基类的对象。 C.基类的对象可以赋值给派生类的对象。 D.间接基类的对象可以赋值给直接基类的对象。 * 北京科技大学计算机系-15- 多态的实现:联编 联编(Binding绑定):确定具体的操作对 象。程序自身彼此关联的过程,确定程序中的 操作调用与执行该操作的代码间的关系。 n静态联编: 编译的多态 n动态联编: 运行时的多态 int a; main() int a; a = 7; * 北京科技大学计算机系-16- 静态联编与动态联编 静态联编(静态束定) n联编工作出现在编译阶段,用对象名或者类名来 限定要调用的函数。 动画 动态联编 n联编工作在程序运行时执行,在程序运行时才确 定将要调用的函数。 例 例 * 北京科技大学计算机系-17- #include class Point public: Point(double i, double j) x=i; y=j; double Area( ) return 0.0; private: double x, y; ; class Rectangle:public Point public: Rectangle(double i, double j, double k, double l); double Area( ) return w*h; private: double w,h; ; 静态联编例 * 北京科技大学计算机系-18- Rectangle:Rectangle(double i, double j, double k, double l) :Point(i,j) w=k; h=l; void fun(Point y=j; virtual double Area( ) return 0.0; private:double x, y; class Rectangle:public Point public: Rectangle(double i, double j, double k, double l); virtual double Area( ) return w*h; private:double w,h; void fun(Point void main( )/主函数 B0 b0, *p; /声明基类对象和指针 B1 b1;/声明派生类对象 D1 d1;/声明派生类对象 p= fun(p);/调用基类B0函数成员 p= fun(p);/调用派生类B1函数成员 p= fun(p);/调用派生类D1函数成员 B0:display( ) B1:display( ) D1:display( ) * 北京科技大学计算机系-26- void fun(B0 ptr)/普通函数 ptr.display( ); void main( )/主函数 B0 b0, *p; /声明基类对象和指针 B1 b1;/声明派生类对象 D1 d1;/声明派生类对象 b0=b0; fun(b0);/调用基类B0函数成员 b0=b1; fun(b0); /调用基类B0函数成员 b0=d1; fun(b0); /调用基类B0函数成员 B0:display( ) B0:display( ) B0:display( ) * 北京科技大学计算机系-27- 例11.3 将例11.2进行修改,使得程序具有运行时的多态的效果 。 / 例11.3: shape1.h #ifndef SHAPE_H #define SHAPE_H class Shape public: virtual double getArea() const; void print() const; ; / Shape类定义结束 基类Shape的定义 例11.3 课下读懂! * 北京科技大学计算机系-28- 10.3.1 虚函数 要实现运行时的多态,需要以下条件: n必须通过指向基类对象的指针访问和基类成员 函数同名的派生类成员函数; n或者用派生类对象初始化的基类对象的引用访 问和基类成员函数同名的派生类成员函数; n派生类的继承方式必须是公有继承; n基类中的同名成员函数必须定义为虚函数。 * 北京科技大学计算机系-29- 例10.4 虚函数的正确使用。分析以下程序,编译时哪个 语句会出现错误?为什么?将有错误的语句屏蔽掉以后 ,程序运行结果如何?其中哪些调用是静态联编,哪些 是动态联编? #include class BB public: virtual void vf1()coutvf1(); bp-vf2(); bp-vf2(10); bp-f(); * 北京科技大学计算机系-30- void main() DD d; BB *bp= bp-vf1(); bp-vf2(); bp-vf2(10); bp-f(); 将这个语句注释掉后,运 行结果将显示: DD:vf1被调用 BB:vf2被调用 BB:f被调用 函数调用bp-vf2(10);是错 误的。因为派生类的vf2函 数和基类的vf2函数的参数 不同,派生类的vf2就不是 虚函数,而是重载。 其中bp-vf1()调用是动态联编。 bp-vf2()是静态联编。 bp-f()也是静态联编。 * 北京科技大学计算机系-31- 10.3.2 虚函数的使用 虚函数必须正确的定义和使用。否则,即使在 函数原型前加了virtual的说明,也可能得不 到运行时多态的特性。 n必须首先在基类中声明虚函数。在多级继承的 情况下,也可以不在最高层的基类中声明虚函 数。例如在第二层定义的虚函数,可以和第三 层的虚函数形成动态联编。但是,一般都是在 最高层的基类中首先声明虚函数。 * 北京科技大学计算机系-32- 11.3.2 虚函数的使用 n基类和派生类的同名函数,必须函数名、返回 值、参数表全部相同,才能作为虚函数来使用 。否则,即使函数用virtual来说明,也不具有 虚函数的行为。 n静态成员函数不可以声明为虚函数。构造函数 也不可以声明为虚函数。 n析构函数可以声明为虚函数,即可以定义虚析 构函数。 * 北京科技大学计算机系-33- 10.3.3 虚析构函数 如果用动态创建的派生类对象的地址初始化基 类的指针,创建的过程不会有问题:仍然是先 调用基类构造函数,再执行派生类构造函数。 但是,在用delete运算符删除这个指针的时候 ,由于指针是指向基类的,通过静态联编,只 会调用基类的析构函数,释放基类成员所占用 的空间。而派生类成员所占用的空间将不会被 释放。 * 北京科技大学计算机系-34- #include using namespace std; class Shape public: Shape()coutfoo(); bar函数中调用a对象的 foo,foo中调用虚函数bar, 调用的是哪个bar。 * 北京科技大学计算机系-43- 一个类的虚函数在它自己的构造函数和析构函数中被调用的时 候,它们就变成普通函数了,不“虚”了。也就是说不能在构造 函数和析构函数中让自己“多态”。例如: class A public: A() foo(); / 在这里,无论如何都是A:foo()被调用! A() foo(); / 同上 virtual void foo(); ; class B: public A public: virtual void foo(); ; void bar() A * a = new B; delete a; * 北京科技大学计算机系-44- 多态有什么用? 在面向对象的编程中,首先会针对数据进行抽象(确定基 类)和继承(确定派生类),构成类层次。 类层次的使用者在使用它们的时候,如果仍然在需要基类 的时候写针对基类的代码,在需要派生类的时候写针对派

温馨提示

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

评论

0/150

提交评论