当前位置: 首页 > news >正文

虚函数(Virtual Function)和纯虚函数(Pure Virtual Function)

虚函数(Virtual Function)和纯虚函数(Pure Virtual Function)是实现多态的关键,但它们在使用和含义上有本质的区别。

我将通过一个清晰的对比和总结来解释它们的区别。


一、核心定义对比

特性虚函数 (Virtual Function)纯虚函数 (Pure Virtual Function)
语法virtual ReturnType funcName();virtual ReturnType funcName() = 0;
实现有函数体(提供默认实现)无函数体(不提供实现)
目的允许派生类选择性地重写该函数强制派生类必须重写该函数
所在类可以是普通类或抽象类必须是抽象类
类实例化该类可以被实例化该类不能被实例化

二、详细解释与示例

1. 虚函数 (Virtual Function)

虚函数在基类中有默认的实现。它告诉编译器:“这个函数可能会在派生类中被重写,但如果派生类不重写它,就使用我的这个默认版本。”

示例:

#include <iostream>class Animal {
public:// 虚函数:有默认实现virtual void makeSound() {std::cout << "Some generic animal sound" << std::endl;}// 虚析构函数是必须的!virtual ~Animal() {}
};class Dog : public Animal {
public:// 可以选择性重写void makeSound() override {std::cout << "Woof! Woof!" << std::endl;}
};class Cat : public Animal {// Cat 类选择不重写 makeSound()// 它将使用 Animal 类的默认实现
};int main() {Animal* myDog = new Dog();Animal* myCat = new Cat();myDog->makeSound(); // 输出: Woof! Woof! (调用重写后的版本)myCat->makeSound(); // 输出: Some generic animal sound (调用基类默认版本)delete myDog;delete myCat;return 0;
}
2. 纯虚函数 (Pure Virtual Function)

纯虚函数在基类中只有声明,没有实现(函数体 = 0)。它告诉编译器和程序员:“这个函数只是一个接口规范,所有非抽象的派生类必须提供它自己的实现。”

包含纯虚函数的类称为抽象类,它不能创建对象实例,只能作为接口被继承。

示例:

#include <iostream>// 抽象类
class Shape {
public:// 纯虚函数:定义接口,没有实现virtual double getArea() const = 0;// 纯虚析构函数也必须提供实现(唯一特例)virtual ~Shape() = default;
};class Circle : public Shape {
private:double radius;
public:Circle(double r) : radius(r) {}// 必须重写纯虚函数double getArea() const override {return 3.14159 * radius * radius;}
};class Rectangle : public Shape {
private:double width, height;
public:Rectangle(double w, double h) : width(w), height(h) {}// 必须重写纯虚函数double getArea() const override {return width * height;}
};int main() {// Shape myShape; // 错误!不能实例化抽象类Shape* shape1 = new Circle(5.0);Shape* shape2 = new Rectangle(4.0, 6.0);std::cout << "Circle area: " << shape1->getArea() << std::endl;std::cout << "Rectangle area: " << shape2->getArea() << std::endl;delete shape1;delete shape2;return 0;
}

三、核心区别总结

方面虚函数纯虚函数
实现有默认实现无实现,只有接口
重写要求派生类可以重写(可选)派生类必须重写(强制)
类性质可以是具体类使类成为抽象类
实例化类可以被实例化不能被实例化
设计意图提供可覆盖的默认行为定义必须实现的接口规范

四、如何选择?

  • 使用虚函数:当基类能提供一个有意义的默认实现,而派生类可能需要根据自己的特性修改这个行为时。

    • 例子Animal::move() 可能有一个默认的“移动”实现,但 Bird 类可能会重写它为“飞行”,Fish 类重写为“游泳”。
  • 使用纯虚函数:当基类无法或不应该提供一个有意义的默认实现,它的唯一作用就是为所有派生类定义一个必须遵守的接口时。

    • 例子Shape::getArea() 计算面积。基类Shape根本无法知道如何计算一个“抽象形状”的面积,只有具体的CircleRectangle才知道自己面积的计算方法。

五、一个重要的特例:纯虚析构函数

纯虚析构函数是一个特例。即使它被声明为纯虚函数(virtual ~Base() = 0;),你也必须为它提供一份实现(通常在类外定义)。这是因为派生类的析构函数会隐式调用基类的析构函数。

class AbstractBase {
public:virtual ~AbstractBase() = 0; // 纯虚析构函数声明
};
// 必须提供实现
AbstractBase::~AbstractBase() {// 实现代码(可以是空的)
}

一句话概括

虚函数是“你可以换掉我的实现”,而纯虚函数是“你必须提供你的实现”。


文章转载自:

http://CTM55zgn.bpmtq.cn
http://c6duvS3b.bpmtq.cn
http://1ddSnhmE.bpmtq.cn
http://Yqxp00qu.bpmtq.cn
http://Z2vk4mg4.bpmtq.cn
http://d1iMRSyA.bpmtq.cn
http://meXCwwCw.bpmtq.cn
http://OVmJAhwH.bpmtq.cn
http://UTwOtdOr.bpmtq.cn
http://sjny445E.bpmtq.cn
http://JjHQdvju.bpmtq.cn
http://UPcKA51a.bpmtq.cn
http://uhOXOJD6.bpmtq.cn
http://DOstY1fO.bpmtq.cn
http://NWd6JyeK.bpmtq.cn
http://HLaQd7j2.bpmtq.cn
http://ovwMMnKO.bpmtq.cn
http://0JoDo8bP.bpmtq.cn
http://yOdcGofd.bpmtq.cn
http://A1rInnRq.bpmtq.cn
http://omDe4isL.bpmtq.cn
http://bPIRPuRL.bpmtq.cn
http://GsRynqub.bpmtq.cn
http://rTKe3yh3.bpmtq.cn
http://bDWsNAcv.bpmtq.cn
http://iU25tPFR.bpmtq.cn
http://isBidfkq.bpmtq.cn
http://SZjFPCBM.bpmtq.cn
http://oJMiyBoC.bpmtq.cn
http://u9dtC6uf.bpmtq.cn
http://www.dtcms.com/a/388315.html

相关文章:

  • 03-Linux用户和权限
  • 本地大模型编程实战(35)使用知识图谱增强RAG(1)知识图谱简介
  • Spring —— 拦截器和异常处理
  • JavaScript逆向Hook技术及常用Hook脚本
  • Part04 算法
  • 硬件 - 立创EDA入门实践 - 从DCDC降压芯片带您从原理图到PCB到打板
  • 安全认证哪家强?CISP和HCIE我选......
  • 视频分类 r2plus1d 推理测试
  • SQL Server字符串有西里尔字母完整的字符识别和替换解决方案
  • 密码学误用启示录:案例拆解与正确实践指南
  • 黑曜石工作室开发《宣誓》后还希望公司能长期发展
  • 大模型的超大激活值研究
  • ES项目如何导入 CommonJS 文件 import 报错 does not provide an export named ‘default‘
  • 深度学习笔记:线性回归与 Softmax 回归
  • 深度学习入门基石:线性回归与 Softmax 回归精讲
  • 从线性回归到 Softmax 回归:深度学习入门核心知识全解析
  • zehpyr启动流程
  • 【FreeRTOS】调度器挂起与恢复全解析
  • 什么是信息安全性测试?如何选择第三方检测机构?
  • SSM框架——Spring、SpingMVC、Mybatis
  • MongoDB+cpolar:跨环境数据库管理的无缝方案
  • Java 泛型详解:从基础到实践
  • Python与GDAL库进行遥感图像处理:一个完整的实战教程
  • 构建AI智能体:三十六、决策树的核心机制(二):抽丝剥茧简化专业术语推理最佳分裂点
  • computeIfAbsent用法讲解
  • freertos代码结构
  • C++底层刨析章节一:STL概述与设计哲学:深入理解C++标准模板库的核心
  • 多态的原理与实现机制
  • [C++]异常
  • Windows PE 文件结构详解:从入口到执行的旅程