第十七章 多态 对象独立性_第1页
第十七章 多态 对象独立性_第2页
第十七章 多态 对象独立性_第3页
全文预览已结束

下载本文档

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

文档简介

1、第十七章 多态 对象独立性1、什么是多态1.1 什么是多态一个动作具有不同的含义例如:篮球比赛中,教练下达“防守”命令,中锋和后卫的防守位置和动作各不相同;军训中,教官下达“集合”命令,每个人站的位置各不相同。 2、C+中的多态2.1 多态的实现方式静态绑定(static binding) 动态绑定(dynamic binding)1 2.2 静态绑定一个类存在同名函数,它们可以根据参数类型、参数个数、参数顺序加以区别(函数重载)例如:void print_arr(int * arr, int n); (1) void print_arr(double * arr, int n); (2)2.

2、2.1 静态绑定的特点在编译阶段就可以确定调用哪个函数例如:void main () int a = 1,2,3; double b = 1.1,2.2; print_arr(a, 3); /编译阶段即可确定调用函数(1) print_arr(b, 2); /编译阶段即可确定调用函数(2)2.3 动态绑定定义在一个类层次中的不同类的函数,他们具有相同名字和参数,根据指针指向的对象所在类来确定调用的函数。1 2.3.1 动态方式的特点只有当程序运行时才能确定调用哪个函数(运行期绑定)3.1 任务的提出设计一款游戏,玩家下达“攻击”命令后,己方步兵、坦克兵等向指定位置进行移动。3.2 设计士兵相关

3、的类步兵、坦克兵都是士兵的一种,因此可以将士兵设计为基类,步兵和坦克兵设计为士兵的派生类。class soldier /士兵类public:void move() /士兵移动 cout << “士兵移动 " <<endl; ;class tanker: public soldier /坦克兵类public: void move() cout << "开坦克移动 " <<endl;class foot_soldier : public soldier /步兵类public:void move() cout <&l

4、t; "两条腿移动" <<endl;1 3.3 设计攻击函数void attack (tanker * pt) /坦克兵发起攻击 pt->move(); void attack (foot_soldier * pb) /步兵发起攻击pb->move();3.4 玩家下发攻击指令void main()tanker t;foot_soldier f;attack(&t); /打印”开坦克移动”attack(&f); /打印”靠两条腿移动”3.5 问题的提出开发人员A负责维护攻击函数,A的问题是:坦克兵和步兵既然都是士兵,能否将现有的两个函

5、数合并为以下一个函数?void attack (soldier * ps) ps->move();如果通过基类指针ps可以访问派生类对象该多么方便:当ps指向坦克对象,则调用坦克类的move();当ps指向步兵对象,则调用步兵类的move();3、为什么需要多态开发人员A希望获得如下效果:void main()tanker t;foot_soldier f;attack(&t); / 期望打印”开坦克移动”attack(&f); / 期望打印“靠两条腿移动”但实际结果是:士兵移动士兵移动1 3.6 问题原因foot_soldier f 的内存布局:soldier * ps

6、;foot_soldier f;ps = &f;ps->move();/ps是基类的指针,调用的是基类的move() 3.6 问题的解决使用虚函数在基类的函数前加上virtual关键字:class soldier /士兵类public: virtual void move() cout << “soldier move " <<endl; ;使用虚函数后,对象f的内存布局:派生类的move覆盖了基类的movesoldier * ps;foot_soldier f;ps = &f;ps->move();/ps调用的是foot_sold

7、ier:move() 3.7 使用虚函数的好处void attack (soldier * ps) ps->move();/通过基类指针就可以调用派生类的move 开发人员A只需专注于attack()流程的设计,至于坦克兵和步兵的move()如何实现则完全不用操心,甚至不关心谁会调用attack()。3.8 C+实现多态的方法通过基类指针调用虚函数。如: soldier * ps; tanker t; foot_soldier f; ps = & t; ps->move(); /调用tanker:move() ps = & f; ps->move(); /调用

8、foot_soldier:move()5、抽象类和纯虚函数5.1 问题的提出玩家通过“兵工厂”创造出的士兵不应该是soldier类的对象,只能是tanker类或foot_soldier类的对象,否则:soldier s;s.move();这个士兵到底是开坦克走还是靠两条腿走?5.2 解决之道-将soldier类改为抽象类class soldier /士兵类public:virtual void move() = 0; /士兵移动;5.2 什么是纯虚函数(pure virtual function)virtual void move() = 0; 说明:1、语法格式: virtual 函数类型

9、函数名称(参数列表) = 0;2、作用通知编译器,move的函数体只能由soldier的派生定义, soldier类不能定义move的函数体。3、特点包含虚函数的类无法创建对象(实例化)1 5.3 什么是抽象类(abstract class)包含纯虚函数的类称为抽象类soldier类定义为抽象类后有如下效果:soldier s;编译代码时报如下错误:'soldier' : cannot instantiate abstract class due to following members5.4 为什么需要抽象类soldier类的move()无法确定行动的方式,只能由soldie

10、r类的派生类确定。练习class base public :virtual void xfun()cout <<"base: xfun"<< endl;void yfun() cout << "base:yfun" << endl;class derived: public basepublic:void xfun()cout << "derived:xfun" << endl;void yfun()cout << "deri:yfun" <<endl;void main() /程序的执行结果是什么? base

温馨提示

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

评论

0/150

提交评论