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

加入VIP,免费下载
 

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

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

下载须知

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

版权提示 | 免责声明

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

C++课件第10章多态Word文件下载.docx

1、。下一章再讲。 函数覆盖:这是本章所要讨论的。一、静态联编和动态联编联编是指一个计算机程序自身彼此关联的过程。按照联编所进行的阶段不同,可分为两种不同的联编方法:静态联编和动态联编。1 静态联编 静态联编是指联编工作出现在编译连接阶段,这种联编又称早期联编,因为这种联编过程是在程序开始运行之前完成的,在编译时就解决了程序中的操作调用与执行该操作代码间的关系。下面举一个静态联编的例子,该例子是图形面积的计算。例1:class Point /该类计算点的面积 private: double x, y; /点的坐标public:Point(double i, double j) x=i; y=j;

2、/构造函数double area() const return 0.0; /计算面积;class Rectangle:public point /计算矩型面积 double w, h; /矩型长、宽/构造函数,包含对父类成员变量的初始化Rectangle(double i, double j, double k, double l);/覆盖了父类同名函数area()/ area() const表示函数内不可更改成员变量的值,/保证在该函数内使用的成员变量只是传值,并不发生值的变化double area() const return w*h; Rectangle:Rectangle(double

3、 i, double j, double k, double l):point(i, j) w=k; h=l;void fun(Point &s) /全局函数,传递对象引用couts.area(); void main() Rectangle rec(3.0, 5.2, 15.0, 25.0);fun(rec); 该程序的运行结果为:0。算出了点的面积而不是矩形面积,为什么?虽然实例化了一个矩形对象Rectangle:但是,在调用fun(rec)时,由于Rectangle类继承了Point类,因此Rctangle对象rec实例化时肯定要实例化一个Point,而函数void fun(Point

4、&s)的形参类型正好是Point对象引用,因此编译器在编译时把函数实参绑定到Point对象的引用上。这是静态联编的结果,导致程序输出了所不期望的结果。虽然上面的例子将void fun(Point &s)改为void fun(Rectangle &s)可轻易解决问题,但这不符合多态“一个概念,多种实现”的思想,我们希望的是;维持Point这“一个概念”,让void fun(Point &s)作为对外服务的接口,持有一个指向Point的对象&s,而在具体的矩型、多边型、圆型对象中,动态的按需调用所需的对象。这需要动态联编技术。2动态联编 动态联编实际可以在程序运行时动态识别所需调用的对象。c+规定

5、动态联编是在虚函数的支持下实现的。二、虚函数1 虚函数基本特点如果某类中的一个成员函数被说明为虚函数,这就意味着该成员函数在派生类中可能有不同的实现。当使用一个指针或引用所标识对象操作该成员函数时,对该成员函数调用采取动态联编方式。 声明一个成员函数为虚函数,只需在函数声明前加virtual关键字即可。C+对virtual函数进行动态联编。下面将例1的area()声明为虚函数:例2(为简化,删掉了构造函数):class Point /该类计算点的面积 virtual double area() const return 0.0; /虚函数 /矩型长、宽 /子类也可以不写virtualvirtu

6、al double area() const return w*h; ; 输出结果是375。因为area()声明为虚函数,C+对其动态联编,运行时确定,将fun(rec)中的&s形参绑定到子类对象rec。 形象的说,动态联编是“自下向上”绑定对象的,先看看有没有本类对象,有则绑定本类对象,没有则从最低一级逐级向上绑定,如例2所示。而静态联编是“自上向下”先看看本类有没有合适对象,有则绑定本类对象,没有则从最高一级开始向下查找绑定对象的,如例1所示。2 运行时多态的好处可以只曝露较抽象的基类,而隐藏具体类的实现,用户调用抽象的服务得到的是具体的服务。运行时多态也有利于实现分布式智能化服务。这些好

7、处是与具体语言无关的。对例2作伪代码扩展,可以看出运行时多态的好处。例3(伪代码):class POINT virtual area() /抽象服务类/以下是具体服务类,继承了POINTclass SHAPE1 : POINTvirtual area() class SHAPE2 : POINT virtual area() class SHAPE3 :fun(Point &s) /一个抽象服务接口 s.area() SHAPE1 S1;fun(S1) ;/具体服务,系统动态确定SHAPE1 S2;fun(S2) ;SHAPE1 S3;fun(S3) ;用户只需知道fun()的位置,知道fun

8、()提供计算面积的服务,需要计算具体图形面积时,创建一个该图形对象即可,不必关心这个具体图形面积是哪个对象计算的。这是一种非常优雅的体系结构。3 进一步理解虚函数C+动态联编必需的条件是: 要建立子类型关系。 要有虚函数的说明,只有虚函数才可以动态联编。 要虚函数发挥作用,必须用基类的指针(或引用)指向派生类的对象(比如例2中的fun(Point &s), 只有地址才能体现多态性,要用指针(或引用)调用虚函数。如果在一个函数内调用虚函数,如果默认的this指针有效,是符合本条要求的。例4符合上述要求的动态联编:#include class A public: virtual void act1

9、(); /有虚函数 void act2() act1(); /类成员调用虚函数,有默认的this指针this-/类函数调用虚函数,显式的thisA: /使用了类限定符,this无效,静态联编 void A:act1() coutact1() called; class B: public A /建立子类型关系 virtual void act1();/有虚函数 ; void B:act1() coutact1() called“; void main() B b; b.act2();运行结果是:act1() called B:act1() called A:act1() called3 构造函

10、数调用虚函数在“第9章 继承”曾讲过,派生类构造函数的调用顺序如下: 先调基类的构造函数产生基类对象 再调用派生类构造函数当构造函数内调用虚函数时,仍沿用上述规则,但对虚函数的调用采用的是静态联编而不是动态联编,为什么会这样,先看例5:例5:构造函数中调用虚函数。class A A() /无参构造函数 virtual void f() coutf() called. class B : public A B() f(); /构造函数中调用虚函数void g() f();class C: public B C() virtual void f() coutg()开始绑定对象时,编译器知道的是,g

11、()是一个声明为virtual的成员函数,而且其入口地址放在表格(无论是vtalbeA表还是 vtalbeB表)的第2项,那么编译器编译这条语句的时候就如是转换:call *(pa-vptr)2),(这一行可看作伪代码)。这一项放的是B:g()的入口地址,则就实现了多态。(注意b的vptr指向的是B的虚表vtableB)。C+标准只要求用虚标机制实现多态,至于虚指针vptr到底放在一个对象布局的哪里,标准没有要求,每个编译器自己决定。如果继承体系的基类的virtual成员不多,而且在派生类要重写的部分占了其中的大多数时候,用的虚函数机制是比较好的;但是如果继承体系的基类的virtual成员很多

12、,或者是继承体系比较庞大的时候,而且派生类中需要重写的部分比较少,那就用另一种多态实现机制:“名称查找表”效率会高一些,很多的库都是这样的。三、纯虚函数和抽象类 JAVA语言中有抽象类和接口的语法。JAVA引入接口的目的主要是将抽象类与子类间的is a kind关系与接口与实现类的关系区分开。 C+有抽象类而无接口的语法。但C+的抽象类也可当作接口使用。1纯虚函数纯虚函数是一种特殊的虚函数,它的一般格式如下: class 类名 virtual 返回类型 函数名(参数表)=0; 在许多情况下,在基类中不能对虚函数给出有意义有实现,而把它说明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函

13、数的作用。2抽象类 带有纯虚函数的类称为抽象类。抽象类是一种特殊的类,它是为了抽象和设计的目的而建立的,它处于继承层次结构的较上层。抽象类是不能定义对象的,在实际中为了强调一个类是抽象类,可将该类的构造函数说明为保护的访问控制权限。 抽象类的主要作用是将有关的组织在一个继承层次结构中,由它来为它们提供一个公共的根,相关的子类是从这个根派生出来的。 抽象类刻画了一组子类的操作接口的通用语义,这些语义也传给子类。一般而言,抽象类只描述这组子类共同的操作接口,而完整的实现留给子类。 抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。如果派生类没有重新定义纯虚函数,而派生类只是继承基类的纯虚函数,则这个派生类仍然还是一个抽象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体类了。本章小结: 动态联编下的多态性(主要体现在函数覆盖)是不太容易理解的,可以分成几个层次理解它:1 设计概计和思想,本章的例3作了较好的说明。这是与语言无关的,也是最重要的。2 知道动态联编是“自下向上”而静态联编是“自上向下”绑定对象,对于阅读和编写程序很有帮助。这虽是实现层面的东西,但几乎也与语言无关,因为面向对象语言都按此顺序绑定对象。3 具体到C+,通过理解虚表,理解动态联编是怎样实现的,为什么需要指针或引用调用虚函数。本章课后习题:理解例1-例5的代码

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

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