版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第6章 多态性和虚函数,6.1 多态性,多态性、封装性和继承性构成了面向对象程序设计的三大特性。 多态性是指发出同样的消息被不同类型的对象接收时导致完全不同的行为。即对应相同的函数名,却执行了不同的函数体。这种把函数名与其具体的实现代码相联系的过程,称为联编。 按照联编进行的阶段的不同,可以分为静态联编和动态联编。 这两种联编过程分别对应着多态的两种实现方式:编译时多态、运行时多态。,6.1.1 编译时多态 静态联编,静态联编是在程序开始运行之前进行。在编译、连接过程中,系统就可以根据类型匹配等特征确定某一个同名标识到底是要调用哪一段程序代码。 编译时多态通过函数重载实现。函数重载的两种方式:
2、 在同一类中重载:同名的成员函数,根据参数个数、类型不同,自动予以区别。 基类成员函数在派生类中的重载。 静态联编有时会出现一些意想不到的结果,请看下面的例子。,#include class Point public: Point(double i, double j) x=i; y=j; double Area( ) const return 0.0; private: double x, y; ;,class Rectangle:public Point public: Rectangle(double i, double j, double k, double l); double Ar
3、ea( ) const return w*h; private: double w, h; ; Rectangle:Rectangle(double i, double j, double k, double l):Point(i, j) w=k; h=l; ,void main( ) Rectangle rec(3.0, 5.2, 15.0, 25.0); Point *prtP= 该程序的运行结果为: 0 输出结果表明基类指针ptrP 指向派生类对象,然而此时ptrP-Area( )调用的是基类的Area( )函数,因为通过基类指针只能取得派生类中从基类继承的数据与函数。,6.1.2 运行
4、时多态动态联编,从上例中可以看出,静态联编时,通过基类指针只能取得派生类中从基类继承的数据与函数。如果我们需要通过基类的指针得到派生类对象中成员函数的调用,能够实现吗?答案是肯定的,通过虚函数可以达到这个目的,从而实现程序的运行时多态,6.2 虚函数,虚函数是动态联编的基础。虚函数是成员函数,而且是非static的成员函数。,6.2.1 虚函数,virtual 类型说明符 函数名(参数表) 其中,被关键字virtual说明的函数称为虚函数。 如果某类中的一个成员函数被说明为虚函数,这就意味着该成员函数在派生类中可能有不同的实现。通过基类指针可以访问派生类对象成员函数。,【例6-2】通过基类指针
5、可以访问派生类对象成员函数,#include class Point public: Point(double i, double j) x=i; y=j; virtual double Area( ) const return 0.0; private: double x, y; ;,class Rectangle:public Point public: Rectangle(double i, double j, double k, double l); /double Area( ) const return w*h; virtual double Area( ) const retur
6、n w*h; private: double w, h; ;,Rectangle:Rectangle(double i, double j, double k, double l):Point(i, j) w=k; h=l; void fun(Point ,程序运行结果: 375.0 通过这个例子可以看到,派生类中对基类的虚函数进行替换时,要求派生类中说明的虚函数与基类中的被替换的虚函数之间满足如下条件: 1 与基类的虚函数有相同的名称。 2 与基类的虚函数有相同的参数个数及相同的对应参数类型。 3 与基类的虚函数有相同的返回值。 如果从名称、参数及返回值三个方面检查之后,派生类的函数满足了上
7、述条件,就被自动确定为虚函数,可以不必加virtual显式说明。,派生类中对基类的虚函数进行替换时,要求派生类中说明的虚函数与基类中的被替换的虚函数之间满足如下条件: 1 与基类的虚函数有相同的名称。 2 与基类的虚函数有相同的参数个数及相同的对应参数类型。 3 与基类的虚函数有相同的返回值。 如果从名称、参数及返回值三个方面检查之后,派生类的函数满足了上述条件,就被自动确定为虚函数,可以不必加virtual显式说明。,【例6-3】动态多态举例,#include class A public: virtual void act1( ); void act2( ) act1( ); this-a
8、ct1( ); A:act1( ); ;,void A:act1( ) coutA:act1( ) called.endl; class B : public A public: void act1( ); ; void B:act1( ) coutB:act1( ) called.endl; void main( ) B b; b.act2( ); ,【例6-4】在构造函数中调用虚函数。,#include class A public: A( ) virtual void f( ) coutA:f( ) called.n; ; class B : public A public: B( )
9、f( ); void g( ) f( ); ;,class C : public B public: C( ) virtual void f( ) coutC:f( ) called.n; ; void main( ) C c; c.g( ); 上面程序的输出结果是: A:f( ) called. C:f( ) called.,6.2.2 纯虚函数,纯虚函数是一种特殊的虚函数,定义纯虚函数的一般格式为: class virtual 类型 函数名(参数表)=0; ; 在许多情况下,在基类中不能对虚函数给出有意义的实现,它的实现留给该基类的派生类去做,这就是纯虚函数。,【例6-5】纯虚函数举例。,
10、#include class point public: point(int i=0, int j=0) x0=i; y0=j; virtual void set( ) = 0; virtual void draw( ) = 0; protected: int x0, y0; ;,class line : public point public: line(int i=0, int j=0, int m=0, int n=0):point(i, j) x1=m; y1=n; void set( ) coutline:set( ) called.n; void draw( ) coutline:
11、draw( ) called.n; protected: int x1, y1; ;,class ellipse : public point public: ellipse(int i=0, int j=0, int p=0, int q=0):point(i, j) x2=p; y2=q; void set( ) coutellipse:set( ) called.n; void draw( ) coutellipse:draw( ) called.n; protected: int x2, y2; ;,void drawobj(point *p) p-draw( ); void seto
12、bj(point *p) p-set( ); ,void main( ) line *lineobj = new line; ellipse *elliobj = new ellipse; drawobj(lineobj); drawobj(elliobj); coutendl; setobj(lineobj); setobj(elliobj); coutnRedraw the object.n; drawobj(lineobj); drawobj(elliobj); ,6.2.3. 抽象类,带有纯虚函数的类是抽象类。抽象类的主要作用是通过它为一个类族建立一个公共的接口,使它们能够更有效地发挥
13、多态特性。 抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。如果派生类没有给出全部纯虚函数的实现,只是继承基类的纯虚函数,则这个派生类仍然还是一个抽象类。如果派生类中给出了基类所有纯虚函数的实现,则该派生类就不再是抽象类了,而是一个可以创建对象的具体类了。 抽象类不能实例化,即不能声明一个抽象类的对象。但是,我们可以声明一个抽象类的指针和引用。通过指针或引用,我们就可以指向并访问派生类对象,进而访问派生类的成员,这种访问是具有多态特征的。,6.2.4 虚析构函数,在析构函数前面加上关键字virtual进行说明,称该析构函数为虚析构函数。 如果一个基类的析构函数被说明为虚析构函数,则它的
14、派生类中的析构函数也是虚析构函数,不管它是否使用了关键字virtual进行说明。 说明虚析构函数的目的在于在使用delete运算符删除一个对象时,能保证析构函数被正确地执行。,【例6-6】虚析构函数举例。,#include class A public: virtual A( ) coutA:A( ) Called.n; ; class B : public A public: B(int i) buf = new chari; ,virtual B( ) delete buf; coutB:B( ) Called.n; private: char * buf; ;,void fun(A *a) delete a; void main( ) A
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 我的梦想:小学生理想与目标教育主题班会课件
- 财务部发送员工季度绩效奖金发放明细确认函5篇
- 科技筑梦新时代英语开眼看世界:小学主题班会课件
- 护理文书书写规范试题(含答案)-1
- 一年级下拔尖题目及答案
- 小学主题班会课件:法制教育与安全意识提升
- 推进数字化转型项目商洽函(4篇)范文
- 项目团队协作流程规划手册
- 抵制校园冷暴力筑牢友善成长防线几年级主题班会课件
- 健康生活每一天活力课堂我来做主小学主题班会课件
- 2026年江苏省启东市高考物理自主招生模拟卷附答案详解【培优B卷】
- 2026年国开电大专科《人文英语1》机考第一大题交际用语能力测试备考题(轻巧夺冠)附答案详解
- 2026年中级经济师之中级工商管理-必背题库含完整答案详解(必刷)
- 北师大版八年级数学下册 第三章 图形的平移与旋转(全章题型归纳)
- 儿童扁桃体切除术后护理要点
- 高中数学联赛二试计数组合专题卷
- 护理实习生综合培训
- 2026春苏教版(新教材)小学科学二年级下册每课必背知识点附目录
- 第24章 数据的分析 单元测试(含答案)-2025-2026学年八年级下册数学人教版
- 内分泌科质控的年度工作述职
- 雅思8000词汇表单
评论
0/150
提交评论