虚函数与运行时多态

2025年3月17日 | 阅读 3 分钟

虚函数是指在基类中声明时使用 virtual 关键字,并在派生类中重新定义(重写)的成员函数。延迟绑定指令指示编译器在运行时通过将对象与适当调用的函数匹配来执行调用的函数。这种方法被称为运行时多态性。

  1. 无论使用何种类型的引用(或指针)来调用函数,虚函数都能确保为对象调用正确的函数。
  2. 它们的主要目的是实现运行时多态性。
  3. 在基类中,函数使用 virtual 关键字声明。
  4. 函数调用在运行时进行解析。

多态性是一个用于描述能够呈现多种形式的术语。如果存在通过继承相互关联的类层次结构,就会发生多态性。多态性可以概括为“在不同上下文中表现出不同的特性”,并且是“多态性”。

虚函数有什么用?

虚函数主要用于实现运行时多态性。只有基类类型指针(或引用)才能启用运行时多态性。基类指针还可以指向基类对象和派生类对象。

此外,即使不知道派生类对象的类型,我们也可以使用虚函数编译基类指针列表并调用任何派生类的方法。

示例

输出

Virtual functions and runtime polymorphism

虚函数的规则是什么?

  1. 虚函数不允许是静态的,也不能是其他类的友元。
  2. 需要基类类型的指针或引用才能访问虚函数。
  3. 基类和任何派生类都应使用相同的函数原型。
  4. 类中不能有虚构造函数。但是,它可能有一个虚析构函数。
  5. 它们总是由基类定义,并由派生类重新定义。

什么是运行时多态性?

运行时多态性是在运行时将对象与功能绑定的过程。覆盖方法是实现运行时多态性的一种方式。在运行时,而不是编译时,Java 虚拟机决定调用哪个方法。也称为动态绑定或后期绑定。根据这个概念,父类的方法在子类中被覆盖。术语“方法重写”是指子类专门实现其父类之一提供的方法的情况。您可以在下面的示例中看到运行时多态性。

示例

输出

Virtual functions and runtime polymorphism

虚函数是如何工作的?

如下所述,如果一个类有一个虚函数,编译器会执行两项任务。

  1. 如果创建了该类的对象,则会添加一个虚指针 (VPTR) 作为该类的数据成员,该指针指向该类的 VTABLE。为每个创建的新对象添加一个新的虚指针作为类的数据成员。
  2. VTABLE 是一个函数指针的静态数组,它是类的一个成员,无论是否生成对象。该表中每个虚函数所在单元格中都包含该类的地址。

虚函数的局限性是什么?

  1. 较慢:虚机制导致函数调用花费的时间稍长,并且由于编译器在编译时无法确定将调用哪个函数,因此优化难度更大。
  2. 在复杂系统中,虚函数会使确定函数从何处调用变得稍微复杂,从而增加了调试难度。