C++ 纯虚函数

2025年8月29日 | 阅读 7 分钟

在 C++ 中,纯虚函数是在基类中声明的虚函数,派生类必须重写它。函数声明以 = 0 结尾,这表示它不能在类体内包含任何默认实现。但是,如果需要,它仍然可以在类体外部定义。

任何继承自基类的类都必须定义该函数。如果一个类至少有一个纯虚函数,它就被认为是抽象类,不能直接用来创建对象。抽象类充当其他类的蓝图,确保派生类提供必要的功能。

语法

它具有以下语法。

在这个语法中,

  • "virtual" 关键字表示该函数是多态的。
  • "= 0" 表示该函数是纯虚函数,这意味着它是抽象的,在基类中没有实现。

C++ 纯虚函数示例

让我们以一个例子来说明 C++ 中的纯虚函数。

示例

编译并运行

输出

The area of the Circle is: 153.938
The area of the Rectangle is: 195
The area of the Triangle is: 27

说明

在此示例中,我们使用抽象基类 Shape 中的名为 calculatingArea() 的纯虚函数来显示运行时多态。Circle、Rectangle 和 Triangle 类重写此函数以计算并显示它们各自的面积。

纯虚函数的特点

纯虚函数在 C++ 中有几个特点。主要特点如下:

  • 基类中无实现:基类中的纯虚函数声明为 = 0,表示不应用任何实现。它的主要目的是作为占位符,表示派生类必须实现。
  • 定义抽象类:如果一个类只包含一个纯虚函数,它就变成了一个抽象类。
  • 确保通用接口:纯虚函数提供了一个标准化的接口。它们要求所有子类实现特定的函数,这有助于保持来自同一基类的派生类型之间的一致性。
  • 运行时多态:纯虚函数使用动态(晚期)绑定,这意味着根据运行时实际的对象类型调用相应的函数,尤其是在通过基类指针或引用访问时。
  • 充当契约:纯虚函数有效地构成了一个契约,要求任何继承自基类的类实现指定的函数。这有助于防止在开发过程中遗漏或不一致的方法定义。
  • 在编译时检查:编译器应用实现规则。如果子类未能重写必需的函数,将在构建时抛出错误,这有助于减少运行时意外并提高可靠性。

关于 C++ 纯虚函数的有趣事实

关于 C++ 纯虚函数有一些有趣的方面。其中一些如下:

1) 派生类中不允许移除

在 C++ 中,基类中声明的纯虚函数不能在派生类中移除或留空。每个子类都必须提供实际的实现;否则,它就是抽象的。

说明

在此示例中,派生类必须重写纯虚函数才能成为一个完整的(非抽象)类。

2) 不能实例化抽象类

任何包含至少一个纯虚函数的类都被视为抽象类,不能直接创建。

示例

编译并运行

输出

main.c:9:12: error: cannot declare variable 'obj_1' to be of abstract type 'Parent'

说明

在此示例中,抽象类对象由于缺少实现而不完整,无法创建。

3) 派生类中必须重写

在 C++ 中,派生类必须重写所有纯虚函数。如果省略,派生类将变成抽象类,也无法实例化。

示例

编译并运行

输出

Child implementation

说明

在此示例中,子类重写了该函数,这使得它可以被创建和使用。

4) 基类可以有构造函数

在 C++ 中,如果基类包含纯虚函数,它仍然可以有构造函数。当创建派生类对象时,将执行此构造函数。

示例

编译并运行

输出

Parent constructor
Child run function

说明

在此示例中,我们首先调用父类构造函数,然后调用子类函数。

5) 在基类中定义纯虚函数是非法的

在 C++ 中,在基类中内联定义纯虚函数是非法的。但是我们可以将其定义在类外部。

示例

编译并运行

输出

Compilation Error

说明

在此示例中,纯虚函数旨在由派生类实现,而不是由父类本身实现。

纯虚函数的优点

C++ 中纯虚函数的几个优点如下:

  • 强制执行接口一致性:所有派生类都必须实现特定的方法并保持一致的结构。
  • 启用多态:它启用了动态绑定的多态性,允许对象根据运行时类型表现出不同的行为。
  • 避免对象创建:具有纯虚函数的抽象类无法实例化,这可以防止滥用。
  • 模块化:通过将接口与实现分离来促进模块化,从而可以更轻松地进行扩展和维护。
  • 编译时安全性:它通过及早检测未实现的函数来提高编译时安全性,从而减少运行时错误。
  • 支持设计模式:它为工厂方法和模板方法等模式奠定了基础,从而实现了可扩展的设计。

纯虚函数的缺点

C++ 中纯虚函数的几个缺点如下:

  • 增加了复杂性:重写类层次结构会使代码维护复杂化。
  • 僵化的接口:更改或删除纯虚函数可能会给现有子类带来问题。
  • 无共享默认值:基类无法提供默认逻辑,导致代码重复。
  • 轻微的运行时成本:动态分派对性能关键型应用程序有轻微影响。
  • 紧耦合:基类的任何更改都需要更新所有子类,这会增加编译时的依赖性。
  • 范围有限:它适用于多态设计,但对于更简单的或非分层结构不是必需的。

C++ 纯虚函数选择题

1) 以下哪个选项是 C++ 纯虚函数的最佳定义?

  1. virtual void show();
  2. void show() = 0
  3. virtual void show() = 0
  4. void show()
 

答案:c) virtual void show() = 0;


2) 在类中声明纯虚函数的目的是什么?

  1. 建立默认行为。
  2. 创建全局变量。
  3. 禁止函数重写
  4. 要求派生类重写该函数。
 

答案:d) 要求派生类重写该函数


3) 在 C++ 中,当派生类未重写纯虚函数时会发生什么?

  1. 派生类变成抽象类
  2. 函数被自动继承
  3. 基类被销毁
  4. 程序发出警告运行
 

答案:a) 派生类变成抽象类。


4) 以下关于抽象类的说法在 C++ 中是正确的?

  1. 没有构造函数
  2. 没有成员函数可用
  3. 它们可以直接使用
  4. 至少应有一个纯虚函数
 

答案:d) 至少应有一个纯虚函数


5) 为什么 C++ 对纯虚函数强制执行编译时测试?

  1. 防止内存泄漏
  2. 及早检测缺失的实现
  3. 降低编译器速度
  4. 启用对象切片
 

答案:b) 及早检测缺失的实现