面向对象程序设计.pptx
《面向对象程序设计.pptx》由会员分享,可在线阅读,更多相关《面向对象程序设计.pptx(61页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、2023/2/241提出问题【例5-1】在例4-1程序中存在的两个不足:(1)基类Pay()和Display()的函数体均为空,在实现部分仍要写出函数体,显得冗余。(2)在主函数中,建立了4个不同类的对象,进行了类似的操作,重复写了4遍类似的语句,程序不够简洁。第1页/共61页2023/2/242分析问题基类设置成员函数Pay()和Display()的目的是为了统一规定类簇的基本行为,虽有冗余,但也必要。为此,C+提供了纯虚函数来解决此问题。第2页/共61页2023/2/243在主函数中建立了4个不同类的对象,进行了类似的操作,重复写了4遍类似的语句。应该怎样有效地来处理它们同样的行为呢?我们
2、首先想到的是用循环解决,但调用这些同名函数的对象却不相同。分析这些对象有一个共同点,那就是来自于同一个基类,而基类与派生类对象有什么关系呢?事实上,它们遵循类型兼容规则。第3页/共61页2023/2/244Employee*emp4=&m1,&t1,&s1,&sm1;/声明抽象类指针数组for(int i=0;iPay();/单一指令,实现多态,计算指针指向对象的工资empi-Display();/单一指令,实现多态,输出指针指向对象的信息第4页/共61页2023/2/2455.2类型兼容规则类型兼容规则是指在需要基类对象的任何地方,都可以使用公有派生类的对象来替代。第5页/共61页2023/
3、2/246通过公有继承,派生类得到了基类中除构造函数、析构函数之外的所有成员。这样,公有派生类实际就具备了基类的所有功能,凡是基类能解决的问题,公有派生类都可以解决。第6页/共61页2023/2/247类型兼容规则中所指替代包括以下情况:(1)派生类的对象可以赋值给基类的对象。(2)派生类的对象可以初始化基类的引用。(3)派生类的对象的地址可以赋值给基类的指针变量。在替代之后,派生类对象就可以作为基类的对象使用,但只能访问从基类继承的成员。第7页/共61页2023/2/248【例5-3】示例类型兼容规则的应用。教材P261,该程序的运行结果为:Base classBase classBase
4、classDerivel classDerive2 class 第8页/共61页2023/2/249根据类型兼容规则,基类指针p可以指向派生类对象obj2、obj3(即派生类对象可以代替基类对象,给基类指针赋值),但编译时,编译器根据p的类型是基类型,自动调用基类的who(),所以结果如上所示。第9页/共61页2023/2/2410【思考题5-3】如果基类指针要访问派生类的who(),怎么办?C+提供了多态机制来解决这个问题。类型兼容规则是C+多态的重要基础。第10页/共61页2023/2/2411多态多态(Polymorphism)是指具有相似功能的不同函数使用同一个名称来实现,从而可以使用
5、相同的调用方式来调用这些具有不同功能的同名函数的特性。第11页/共61页2023/2/24125.4 多态的分类C+支持的多态可以分为四种类型:重载多态:函数重载和运算符重载强制多态:强制类型转换包含多态:虚函数参数多态:函数模板和类模板 第12页/共61页2023/2/2413联编联编是指把一个标识符名和一个存储地址联系在一起的过程。即函数调用与某个函数在多态的实现过程中,确定调用哪个同名联系的过程,又称绑定。分为:静态联编动态联编第13页/共61页2023/2/2414静态联编是在编译阶段完成的联编。例5-2、例5-3及以前的函数重载都是采用静态联编方式。例5-4,教材P265,是静态联编
6、。动态联编是在运行阶段完成的联编。第14页/共61页2023/2/2415在例5-4中,静态联编把基类指针ps指向的对象绑定到基类上,而在运行时进行动态联编将把ps指向的对象绑定到派生类上。第15页/共61页2023/2/2416可见,同一个指针,在不同阶段被绑定的类对象将是不同的,进而被关联的类成员函数也是不同的。如何来确定是用静态联编还是用动态联编呢?C+规定,动态联编通过继承和虚函数来实现。第16页/共61页2023/2/2417虚函数是动态联编的基础。下面介绍虚函数。第17页/共61页2023/2/24185.6 虚函数虚函数就是在基类中被关键字virtual说明、并在一个或多个派生类
7、中被重新定义的成员函数。第18页/共61页2023/2/2419声明虚函数的格式如下:virtual ();第19页/共61页2023/2/2420在派生类中重新定义虚函数时,其函数原型包括返回类型、函数名、参数个数与参数类型的顺序,都必须与基类中的原型必须相同。第20页/共61页2023/2/2421一个函数一旦被声明为虚函数,则无论声明它的类被继承了多少层,在每一层派生类中该函数都保持虚函数特性。因此,在派生类中重新定义该函数时,可以省略关键字virtual。但是,为了提高程序的可读性,往往不省略。第21页/共61页2023/2/2422在程序运行时,不同类的对象调用各自的虚函数,这就是运
8、行时多态。第22页/共61页2023/2/2423【例5-5】将例5-4基类的成员函数print()设为虚函数,采用对象指针调用虚函数,进而实现动态联编。第23页/共61页2023/2/2424该程序的运行结果为:A studentA graduate studentA studentA studentA graduate student第24页/共61页2023/2/2425【思考题5-5】如果将例5-5中Student类改为:class Studentpublic:virtual void print();/虚函数的声明;virtual void Student:print()/虚函数的实
9、现 coutA studentendl;第25页/共61页2023/2/2426注意:当有虚函数声明时,virtual关键字只用在虚函数的声明中,不能用在虚函数定义中。第26页/共61页2023/2/2427【思考题5-4】将例5-5中用对象调用虚函数,其结果如何?【注意】只有通过对象指针或对象引用来调用虚函数,才能实现动态联编。如果采用对象来调用虚函数,则采用的是静态联编方式。第27页/共61页2023/2/2428【例5-6】将例5-4基类的成员函数print()设为虚函数,采用对象引用调用虚函数,进而实现动态联编。第28页/共61页2023/2/2429运行结果表明,只要定义一个基类的对
10、象指针或对象引用,就可以调用期望的虚函数。思考题:如果将对象引用或对象指针换为对象,那么是静态联编。第29页/共61页2023/2/2430在实际应用中,编程人员不必过多地考虑类的层次关系,无须显式地写出虚函数的路径,只须将对象指针指向相应的派生类或引用相应的对象,通过动态联编就可以对消息做出正确的反应。第30页/共61页2023/2/2431小结(1)如果你期望在派生类中重新定义一个成员函数,那么你就应该在基类中把该函数设为virtual。(2)以单一指令调用不同函数,这种性质就是多态。(3)虚函数是C+语言的多态性质和动态绑定的关键。(4)虚函数派生下去仍是虚函数,而且可以省略virtua
11、l关键词。第31页/共61页2023/2/2432【思考题5-8】虚函数与虚拟继承有什么相似的地方?他们之间有没有联系?如果能了解C+编译器对于虚函数的实现形式,我们就能知道为什么虚函数可以实现动态绑定。下面介绍虚函数表。第32页/共61页2023/2/24335.6.3 虚函数表为了达到动态绑定的目的,C+编译器通过某个表格,在执行期间“间接”调用实际上欲绑定的函数,这样的表格称为虚函数表(vtable)。第33页/共61页2023/2/2434每一个含有虚函数的类,编译器都为它做一个虚函数表,表中的每一项都指向一个虚函数的地址,实现上是一个函数指针的数组。此外,编译器也会为类加上一个数据成
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 面向 对象 程序设计
限制150内