ImageVerifierCode 换一换
格式:DOCX , 页数:18 ,大小:24KB ,
资源ID:2837138      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/2837138.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(54虚函数与多态.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

54虚函数与多态.docx

1、54虚函数与多态5.4 虚函数与多态多态是面向对象程序设计的三大重要特征之一。作为C+中的术语,多态是指使用相同的函数名来访问函数不同实现的方法。正因为如此,多态也可以被描述为“一种接口,多种方法”。也就是说可以使用相同的形式来访问一组通用的运算,即使与每个运算对应的具体行为可能不同。C+支持编译时多态和运行时多态。运算符重载和函数重载就是编译时多态的一种表现。虽然运算符重载和函数重载的功能很强大,但它们不能满足一个完整的面向对象语言的全部需求。因此,在C+中除了实现编译时多态之外,还使用派生类和虚函数来实现运行时多态,这也是本章的主题。本章首先将简短地讨论指向派生类型的指针,因为它们提供了对

2、运行时多态的支持。5.4.1 指向派生类型的指针基类型的指针可以指向其派生类的对象。运行时多态的基础是基类型指针。基类型指针和派生类型指针可以通过多种方法进行关联,而其他类型的指针则不能。在前面讲到,某个类型的指针一般不能指向其他类型的对象,但基类型指针和派生类型指针除外。在C+中,基类型指针可以指向任何派生类型的对象。例如,假设有一个基类B_ class和一个B_ class的派生类D_ class。在C+中,所有被声明为指向B_ class类型的指针同时也可以指向D_ class类型。因此,假设: B_ class *p;/B_ class类型的指针 B_ class B_ ob;/B_

3、class类型的对象 D_ class D_ ob;/D_ class类型的对象那么下面两条语句是完全合法的: p=&B_ ob; /p指向B_ class类型的对象 p=&D_ ob; /*p指向D_ class类型的对象,这个类派生于B_ class*/在上面的代码中,p可以用来访问D_ ob中所有从B_ ob继承的成员,但不能访问D_ ob中定义的成员。下面我们再来看一个更具体的示例,下面的程序定义了一个基类 B_ class和一个派生类D_ class,程序中使用了简单的类层次结构来保存作者姓名和书名。/使用基类型指针访问派生类型对象#include #include / for ol

4、der compilers, use using namespace std;class B_ class char author80;public: void put_author(char *s) strcpy(author, s); void show_ author() cout author n; ;class D_ class : public B_ class char title80;public: void put_ title(char *num) strcpy(title, num); void show_ title() cout Title: ; cout title

5、 put_ author(Tom Clancy); /通过基类型指针访问D_ class类型的对象 p = &D_ ob; p-put_ author(William Shakespeare); /输出保存在对象中的每个作者姓名 B_ ob. show_ author(); D_ ob. show_ author(); cout put_ title(The Tempest); p-show_ author(); /这里既可以使用指针p也可以使用指针dp dp-show_ title( ); return 0;程序输出如下: Tom Clancy William Shakespeare Wil

6、liam Shakespeare Title:The Tempest在上面的示例中,指针p被声明为指向B_ class类型的指针。同时,它可以指向一个派生类D_ class类型的对象并且可以用来访问派生类中从基类继承的成员。但要记住,基类型指针不能访问在派生类中定义的成员。这就是为什么程序需要通过派生类型的指针dp来访问函数show_ title()的原因。如果想通过基类型指针来访问在派生类中定义的成员,必须先把它转换为派生类型的指针。例如,下面这行代码就可以正确地调用D_ ob的成员函数show_ title()。(D_ class *)p)-show_ title();其中,在类型转换运算

7、外部的圆括号是必需的,因为我们需要转换的是指针p的类型,而不是调用函数show_ title()所返回的类型。尽管这种指针类型的转换方式在技术上没有任何错误,但最好还是避免这样做,因为这容易混淆代码(事实上,大多数C+程序员都认为这是一种不好的形式)。需要知道的另外一点是:基类型指针可以指向任何派生类型的对象,反之则不然。也就是说,我们不能使用派生类型的指针来访问基类型的对象。指针的增量运算或减量运算依赖于指针被声明的类型。因此,当基类型指针指向派生类型的对象时,指针的增量运算或减量运算将不会使指针指向下一个派生类型的对象,相反,它将指向(指针认为是这样)下一个基类型的对象。因此,当基类型的指

8、针指向派生类型对象时,指针的增量运算或减量运算是无效的。基类型指针可以指向任何派生类型的对象,这一点很重要,它也是C+的基础。我们马上将会学到,基类型指针的这种灵活性是C+得以实现运行时多态的关键。派生类型的引用与刚才描述的指针行为一样,基类型的引用也可以指向派生类型的对象。最常见的用法是在函数参数的声明和定义中。基类型的引用参数可以接收基类型的对象或其派生类型的对象。5.4.2 虚函数运行时多态的实现需要将两个特征结合在一起,即继承和虚函数。在前面章节中你已经学习了继承,下面我们就来学习虚函数。在函数声明前加virtual可以声明虚函数。虚函数是指在基类中使用virtual声明,并且在一个或

9、多个派生类中被重新定义的函数。这样,每个派生类可以拥有自己的虚函数定义。我们最感兴趣的是:在使用基类型指针(或引用)来调用虚函数时,虚函数所发生的行为。在这种情况下,C+根据指针指向对象的类型来决定调用虚函数的哪个定义,并且这种决定是在运行时作出的。这样,当指针指向不同的对象时,将会执行虚函数的不同定义。换言之,是指针指向对象的类型(而不是指针的类型)来决定虚函数的调用。因此,如果在一个基类中包含一个虚函数,并且这个基类有两个或多个派生类,那么当一个基类指针指向不同类型的对象时,虚函数的不同定义将被执行。同理,基类型的引用也是如此。在基类中声明虚函数需要在函数声明前加关键字virtual。当虚

10、函数在派生类中重新定义时,关键字virtual不需要重复(当然重复也不是个错误)。定义了虚函数的类被称为多态类。包含虚函数的类被称为多态类,这个术语同样适用于从多态类继承的类。下面的程序给出了虚函数的用法:/使用虚函数的示例。#include using namespace std;class base public:在类base中,函数who()被声明为虚函数,这说明该函数可以在派生类中重新定义。因此,在类first_d和second_d中,who()分别被重新定义。 virtual void who( ) /声明虚函数 cout Basen; ;class first_ d : publi

11、c base public: void who( ) /重新定义first_ d中的who() cout First derivationn; ;class second_ d : public base public: void who( ) /重新定义second_ d中的who( ) cout who(); /访问base中的who然后,p被赋予first_obj的地址。前面讲过,基类型的指针可以指向任何派生类型的对象。现在,当who()又被调用,C+再次检查p指向对象的类型,然后根据该类型决定调用相应的who()。由于p指向一个first_d类型的对象,所以who()相应的定义被调用。

12、同理,当把second_obj的地址赋给p时,who()在second_d中的定义被执行。 p = &first_obj; p-who(); /访问first_d中的who p = &second_obj; p-who(); /访问second_d中的who return 0;程序输出如下: Base First derivation Second derivation 记住:程序是在运行时决定调用虚函数的哪个定义。更进一步地说,这个决定只依赖于基类型指针所指向的对象的类型。虚函数可由标准对象通过点运算符调用。这就是说,在前面的示例中,可以通过下面的语句来访问函数who():first_obj

13、.who();但是,这种调用虚函数的方法忽略了虚函数的多态性。只有使用基类型指针访问虚函数的时侯,运行时多态才得以体现。在派生类中重新定义虚函数时,被称为覆盖虚函数。初看上去,虚函数在派生类中的重新定义好像是一种特殊的函数重载形式,但实际上并不是这样。事实上,这两种方法有着本质的不同。首先,重载函数必须在参数的类型或数量上不同,而重新定义的虚函数在参数的类型和数量上必须相同。虚函数的原型与它重新定义的形式必须完全相同。如果原型不同,那么函数只能被简单地认为是重载形式,从而失去了虚函数的特征。另一个限制是,在定义虚函数的类中,虚函数必须声明为类的成员而不能是友员,但虚函数可以被声明为其他类的友员。同样,析构函数可以是虚函数,但构造函数则不可以。正因为在重载一般的函数和重新定义虚函数之间有着差异和限制,我们使用术语“覆盖(overriding)”来描述虚函数的重新定义。5.4.2.1 虚函数的继承

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1