• 1. 第12章 多 态 杨章伟 e-mail:yang505412@163.com
  • 2. 课程内容安排多态 函数重载 虚函数 抽象类 小结 习题
  • 3. 什么是多态 简单来说,多态就是“一个接口,多种实现”,就是同一种事物表现出的多种形态。 在面向对象的概念中,多态性是指不同对象接收到相同消息时,根据对象类的不同而产生不同的动作。多态性提供了同一个接口可以用多种方法进行调用的机制,从而可以通过相同的接口访问不同的函数。具体地说,多态性就是同一个函数名称,作用在不同的对象上将产生不同的操作。
  • 4. 多态的作用 事实上,多态也是人类思维方式的一种直接模拟。比如,一个对象中有很多求两个数最大值的行为,虽然可以针对不同的数据类型,写很多不同名称的函数来实现,但事实上,它们的功能几乎完全相同。这时,就可以利用多态的特征,用统一的标识来完成这些功能。
  • 5. 函数重载 函数重载在前面的章节中也提到过,函数的重载也称多态函数,是实现编译时的多态性的形式之一。它使程序能用同一个名字来访问一组相关的函数,提高了程序的灵活性。函数重载时,函数名相同,但函数所带的参数个数或数据类型不同,编译系统会根据参数来决定调用哪个同名的函数。 面向对象程序设计中,函数的重载表现为两种情况: 第一种是参数个数或类型有所差别的重载。 第二种是函数的参数完全相同但属于不同的类。
  • 6. 虚函数 虚函数是重载的另一种形式,实现的是动态的重载,即函数调用与函数体之间的联系是在运行时才建立,也就是动态联编。前面的内容也提到了,虚函数是实现运行时的多态,即动态多态性的一个重要方式。 一般对象的指针之间没有联系,彼此独立,不能混用。但派生类是由基类派生出来的,它们之间有继承关系,因此,指向基类和派生类的指针之间也有一定的联系。如果使用不当,将会出现一些问题
  • 7. 定义虚函数 虚函数的定义是在基类中进行的,即把基类中需要定义为虚函数的成员函数声明为virtual。当基类中的某个成员函数被声明为虚函数后,其就可以在派生类中被重新定义。在派生类中重新定义时,其函数原型,包括返回类型、函数名、参数个数和类型、参数的顺序都必须与基类中的原型完全一致。一般来说,虚函数定义的形式为: virtual <函数类型><函数名>(参数表) { 函数体 }
  • 8. 使用虚函数 事实上,读者可以看出,在派生类中被重新定义的基类中的虚函数,是函数重载的另一种形式,但它与函数重载又有如下的区别:一般的函数重载,要求其函数的参数或参数类型必须有所不同,函数的返回类型也可以不同,但重载一个虚函数时,要求函数名、返回类型、参数个数、参数的类型和参数的顺序必须与基类中的虚函数的原型完全相同。 如果仅返回类型不同,其余相同,则系统会给出错误信息。 如果函数名相同,而参数个数、参数的类型或参数的顺序不同,系统认为是普通的函数重载,虚函数的特性将丢失。
  • 9. 纯虚函数 当在基类中不能为虚函数给出一个有意义的实现时,可以将其声明为纯虚函数。纯虚函数的实现可以留给派生类完成,纯虚函数的作用是为派生类提供一个一致的接口。一般来说,一个抽象类带有至少一个纯虚函数。纯虚函数是在一个基类中说明的虚函数,它在该基类中没有具体的操作内容,要求各派生类在重新定义时根据自己的需要定义实际的操作内容。纯虚函数的一般定义形式为: virtual<函数类型><函数名>(参数表)=0; 纯虚函数与普通虚函数定义的不同在于书写形式上加了“=0”,说明在基类中不用定义该函数的函数体,它的函数体由派生类定义。
  • 10. 抽象类 带有纯虚函数的类称为抽象类。抽象类是一种特殊的类,其是为了抽象和设计的目的而建立的,处于继承层次结构的较上层。抽象类是不能定义对象的,在实际中为了强调一个类是抽象类,可将该类的构造函数说明为保护的访问控制权限。 抽象类的主要作用是将有关的类组织在一个继承层次结构中,由抽象类来为它们提供一个公共的根,相关的子类是从这个根派生出来的。抽象类刻画了一组子类的操作接口的通用语义,这些语义也传给子类。一般而言,抽象类只描述这组子类共同的操作接口,而完整的实现留给子类。 抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。
  • 11. 本章主要介绍了C++面向对象程序设计的又一个重要特征——多态。简单地说,多态就是要在程序中实现“一个接口,多种实现”,或者说多个属于不同类的函数可共用一个函数名。这和前面介绍的函数的重载不同的是:多态要求函数的参数个数、参数类型和返回类型等都完全相同。本章重点介绍了多态实现的两种形式:函数重载和虚函数。其中函数重载主要实现编译时的多态,即静态多态性,而虚函数主要实现运行时的多态,即动态多态性。最后,本章通过具体的范例就纯虚函数和抽象类的概念和应用做了简要的介绍。小结
  • 12. 1.定义一个Rectangle类,有长itsWidth、宽itsLength等属性,重载其构造函数Rectangle()和Rectangle(int width,int length)。 2.定义一个哺乳动物Mammal类,再由此派生出狗Dog类,二者都定义 Speak()成员函数,基类中定义为虚函数,定义一个Dog类的对象,调用Speak函数,观察运行结果。 3.定义一个Shape抽象类,在此基础上派生出Rectangle和Circle,二者都有GetArea()函数计算对象的面积,GetPerim()函数计算对象的周长。 习题
  • 13. 习题4.定义一个基类BaseClass,从它派生出类DerivedClass,BaseClass中定义虚析构函数,在主程序中将一个DerivedClass的对象地址赋给一个BaseClass的指针,观察运行过程。 【解答】该试题主要考查虚构造函数和虚析构函数的实现,并通过指针进行操作。该试题首先必须定义基类和公有继承于基类的派生类,在基类中定义虚析构函数。在主函数中创建派生类对象后关闭,该析构函数将被执行。