第八部分思维导图PDF下载C++程序设计 第八章 多态性和虚函数

8.1 多态性

8.1.1 静态联编中的赋值兼容性及名字支配规律

  • 对象的内存地址中只包含数据成员,并不存储有关成员函数的信息。
  • 成员函数的地址翻译过程与其对象的内存地址无关。
  • 编译器只根据类型翻译成员函数的地址并判断调用的合法性。

8.12 动态联编的多态性

  • 虚函数的地址翻译取决于对象的内存地址。
  • 派生类能继承基类的虚函数表,只要适合基类同名(参数也相同)的成员函数,无论是否使用virtual声明,他们都自动成为虚函数。
  • 如果派生类没有改写继承基类的虚函数,则函数指针调用基类的虚函数。
  • 如果派生类改写了基类的虚函数,编译器将重新为派生类的虚函数建立地址,函数指针会调用改写过的虚函数。
  • 虚函数的调用规则:根据当前对象,优先调用对象本身的虚成员函数。

静态联编所支持的多态性称为编译时的多态性,如重载函数。

动态联编所支持的多态性称为运行时的多态性,如虚函数。

8.2 虚函数

8.2.1 虚函数的定义

  • 虚函数只能是类中的一个成员函数,但不能是静态成员,关键字virtual用于类中的该函数的声明中。如
    • 声明
      • class A {
      • public:
      • virtual void fun();
      • };
    • 定义
      • void A::fun() { …… }
  • 当在派生类中定义了一个同名的成员函数时,只要该成员函数的参数个数和相应类型以及它的返回类型与基类中的同名的虚函数安全一样,则无论是否为该成员函数使用virtual,它都将称为一个虚函数!

8.2.2 虚函数实现多态性的条件

  • 关键字virtual指示C++编译器对调用虚函数进行动态联编。这种多态性是程序运行到需要的语句出才动态确定的。所以称为运行时的多态性。不多,使用虚函数不一定产生多态性,也不一定适用动态联编。如调用时使用成员名限定,可以强制C++对该函数的调用适用静态联编。
  • 产生运行时的多态性有3个前提(必须同时满足)

    • 1、类之间的继承关系满足赋值兼容规则
    • 2、改写了同名虚函数。
    • 3、根据赋值兼容性规则使用指针。
      • 1、按赋值兼容性规则使用基类指针(或应用)访问虚函数
      • 2、把指针(或引用)作为函数参数,即这个函数不一定是类的成员函数,可能是普通函数,而且可以重载。

8.2.3 构造函数和析构函数调用虚函数

  • 在构造函数和析构函数中调用虚函数采用静态联编,即它们所调用的虚函数是自己的类或基类中定义的函数,而不是任何在派生类中重定义的虚函数。
  • delete运算符和析构函数一起工作。
  • new运算符和构造函数一起工作。

8.2.4 纯虚函数与抽象类

  • 虚函数
    • 不在基类中给虚函数给出定义,将其定义留给派生类去做。
    • 纯虚函数的一般形式
      • class 类名 {
      • virtual 函数类型 函数名(参数列表) = 0;
      • };
  • 抽象类
    • 从抽象类派生的类必须提供纯虚函数的实现代码,或者仍在该派生类中将它说明为纯虚函数。
    • 一个类可以说明多个纯虚函数,包含有纯虚函数的类称为抽象类。
      • 一个抽象类只能作为基类来派生新类,不能说明抽象类的对象了。
      • 可以用抽象类来声明指向抽象类对象的指针(或引用)
    • 通过一个基类派生出一系列的类,则将这些类总称为类族。

    • 抽象类至少含有一个虚函数,且至少有一个虚函数是纯虚函数。
    • 成员函数内可以调用纯虚函数,但因为没有为纯虚函数定义代码,所以在构造函数或者析构函数内调用纯虚函数将导致程序错误。
  • 经典案例

    • 计算几个多边形的面积,首先建立一个抽象基类,只包含一个纯虚函数virtual double area()=0,然后不断派生出三角形、正方形、圆形、矩形等类,再在派生类中定义area()的计算方法,最后在类外定义一个函数total()用于统计所有面积的和。主函数内通过shape *s[5]建立数组,然后s[0] = square(4),s[1]=new rectangle(3,6),s[2]=new circle(10)…等建立实例,最后通过for循环计算每个面积,再用total函数计算总面积。

8.3 多重继承与虚函数

多重继承可以被视为多个单一继承的组合。

8.4 类成员函数的指针与多态性

在派生类中,当一个指向基类成员函数的指针指向一个虚函数,并且通过指向对象的基类指针(或应用)访问这个虚函数时,仍发生多态性。

Written by:Vilen

最后修改日期:十一月 5, 2019

作者

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。