C++ 什么是虚函数?什么是纯虚函数,以及区别?(通俗易懂)

news2024/11/11 5:09:51

📚 当谈到虚函数时,通常是指在面向对象编程中的一种机制,它允许在派生类中重写基类的函数,并且能够通过基类指针或引用调用派生类中的函数。

目录

前言

🔥 虚函数

🔥  纯虚函数

🔥 两者区别

🔥 实践案例

总结


前言

虚函数使得面向对象编程中的多态性得以实现,能够更灵活地处理不同派生类的对象,提高代码的可扩展性和可维护性。


🔥 虚函数

虚函数(Virtual Function)是在面向对象编程中用于实现动态多态性的一种机制。通过将基类中的成员函数声明为虚函数,可以在派生类中重写(Override)这些函数,从而根据对象的实际类型确定调用的函数版本。

声明方式:在基类中用 virtual 关键字声明的函数称为虚函数。

class Base {
public:
    virtual void display() {
        // Base class implementation
    }
};

多态调用:通过基类指针或引用调用虚函数时,实际调用的是指向对象的派生类版本(如果派生类重写了这个函数)。

动态绑定:在运行时根据对象的实际类型来确定调用的函数版本,而不是在编译时静态确定。

虚函数表(vtable):编译器通常通过添加一个指向虚函数表的指针来实现虚函数的机制。虚函数表存储了每个类的虚函数的地址。

代码示例:

#include <iostream>

// 基类 Base
class Base {
public:
    // 虚函数 display,提供默认实现
    virtual void display() {
        std::cout << "Display function of Base class" << std::endl;
    }
};

// 派生类 Derived
class Derived : public Base {
public:
    // 重写基类的虚函数 display
    void display() override {
        std::cout << "Display function of Derived class" << std::endl;
    }
};

int main() {
    Base* basePtr = new Derived(); // 基类指针指向派生类对象
    basePtr->display(); // 调用派生类中的 display 函数
    delete basePtr;
    return 0;
}

Base 类中的 display() 被声明为虚函数,并提供了默认实现。

Derived 类重写了 display() 函数,改变了默认行为。

在主函数中,通过基类指针 basePtr 调用 display() 函数时,实际调用的是 Derived 类中的版本。

🔥  纯虚函数

纯虚函数(Pure Virtual Function)是一个在基类中声明的虚函数,但没有在基类中提供实现。它通过在函数声明的结尾处使用 = 0 来标记:

在很多情况下,基类生成对象很不合理。为了解决这个问题,引入了纯虚函数的概念,将函
数定义为纯虚函数,派生类中必须重写实现纯虚函数。对于实现了纯虚函数的子类,该纯虚
函数在子类中就变成了虚函数。

声明方式

class Base {
public:
    virtual void display() = 0; // Pure virtual function
};

无法实例化类:包含纯虚函数的类被称为抽象类(Abstract Class),不能直接创建实例对象。

强制派生类实现:派生类必须实现基类中的纯虚函数,否则它们也会成为抽象类,无法实例化。

代码示例:

#include <iostream>

// 抽象基类 AbstractBase
class AbstractBase {
public:
    // 纯虚函数 display,没有默认实现
    virtual void display() = 0;
};

// 派生类 Derived 实现抽象基类
class Derived : public AbstractBase {
public:
    // 实现抽象基类中的纯虚函数 display
    void display() override {
        std::cout << "Display function of Derived class" << std::endl;
    }
};

int main() {
    // AbstractBase baseObj; // 不能实例化抽象类
    Derived derivedObj; // 可以实例化派生类
    AbstractBase* basePtr = &derivedObj; // 抽象基类指针指向派生类对象
    basePtr->display(); // 调用派生类中实现的 display 函数
    return 0;
}

AbstractBase 类中的 display() 被声明为纯虚函数,没有提供默认实现,使得 AbstractBase 成为抽象类,不能实例化。

Derived 类继承自 AbstractBase,必须实现 AbstractBase 中的纯虚函数 display

函数中,派生类 Derived 被实例化,而抽象基类 AbstractBase 的指针 basePtr 可以指向 Derived 类对象,并调用其实现的 display() 函数。

无论虚函数还是纯虚函数,定义中都不能有 static 关键字。因为 static 关键字修饰的内容在编译前就要确定,而虚函数、纯虚函数是在运行时动态绑定的。

🔥 两者区别

虚函数 允许在派生类中重写函数,但可以有默认实现。它是可选的,可以在基类中提供实现。

纯虚函数 没有默认实现,派生类必须提供实现。它使得基类成为抽象类,不能实例化。

🔥 实践案例

假设我们有一个基类 Shape,它定义了所有形状的基本属性和行为。我们希望能够计算各种形状的面积,但具体的面积计算方法因形状而异,因此我们可以使用虚函数和纯虚函数来达到这个目的。

🎯 首先,定义 Shape 类作为抽象基类,其中包含一个纯虚函数 area() 用于计算形状的面积:

#include <iostream>

// Abstract base class Shape
class Shape {
public:
    // 纯虚函数用于计算面积
    virtual double area() const = 0;

    // 虚析构函数(对多态性很重要)
    virtual ~Shape() {}
};

🎯 接着,我们可以创建不同类型的形状类(如矩形、圆形)作为 Shape 的派生类,并实现它们的具体面积计算方法。

创建一个矩形类 Rectangle 和一个圆形类 Circle

class Rectangle : public Shape {
private:
    double width;
    double height;

public:
    Rectangle(double w, double h) : width(w), height(h) {}

    // 重写矩形的面积函数
    double area() const override {
        return width * height;
    }
};

class Circle : public Shape {
private:
    double radius;

public:
    Circle(double r) : radius(r) {}

    // 重写圆的面积函数
    double area() const override {
        return 3.14 * radius * radius;
    }
};

🎯 我们可以使用这些类来计算具体形状的面积,而无需关心具体是哪种形状

int main() {
    Rectangle rect(5, 3);
    Circle circle(2.5);

    // 使用 Shape 指针访问派生类 基类的指针指向了子类的对象
    Shape *shape1 = &rect;
    Shape *shape2 = &circle;

    // 使用虚函数计算并打印面积
    std::cout << "Area of Rectangle: " << shape1->area() << std::endl;
    std::cout << "Area of Circle: " << shape2->area() << std::endl;

    return 0;
}


// 运行结果
Area of Rectangle: 15
Area of Circle: 19.625

通过使用虚函数 area() 和纯虚函数 virtual double area() const = 0;,我们实现了多态性,使得能够根据实际的对象类型来调用适当的面积计算方法。同时,基类 Shape 的设计强制所有派生类实现 area() 方法,确保了面积计算的统一性和规范性。

总结

在实际应用中,虚函数和纯虚函数结合使用,通常用来定义接口和基类的通用行为,同时强制派生类实现特定的行为,从而实现一种规范化的设计模式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1904352.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IntelliJ IDEA教育版在Windows电脑中的下载、安装方法

本文介绍IntelliJ IDEA软件Community&#xff08;社区版&#xff09;在Windows操作系统中的下载、安装、运行与使用方法。 IntelliJ IDEA软件是一款由JetBrains公司开发的集成开发环境&#xff08;IDE&#xff09;&#xff0c;主要用于Java语言的开发&#xff0c;但同时也支持其…

win7系统快速安装python

下载安装包 建议选择python3.8左右的&#xff0c;我下载的是3.7.8&#xff0c;最新版本的pythonwin7可能不支持 python网址 下拉寻找 安装python 1.双击安装包 更换完地址选择安装(install) 安装完成后点击close即可 测试是否安装成功 1.winr快捷键打开黑窗口输入cmd …

【Linux】线程(轻量级进程)

目录 一、线程概念 二、线程特性 2.1 进程更加轻量化 2.2 线程的优点 2.3 线程的缺点 2.4 线程的异常 2.5 线程用途 三、进程和线程 四、线程控制 4.1 包含线程的编译链接 4.2 创建线程 4.3 获得线程自身的ID 4.4 线程终止 4.5 线程等待 4.6 线程分离 4.6 线程…

Redis官方可视化管理工具

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl RedisInsight是一个Redis可视化工具&#xff0c;提供设计、开发和优化 Redis 应用程序的功能。RedisInsight分为免费的社区版和一个付费的企业版&#xff0c;免费版具有基本…

thingsboard v3.7 win编译相关问题记录

遇到的问题总结 node\yarn 相关版本问题 3.7 开始需要 JDK17 ui-ngx 模块 yarn 相关问题报错 报错信息 [INFO] Downloading https://github.com/yarnpkg/yarn/releases/download/v1.22.10/yarn-v1.22.10.tar.gz to D:\soft\maven\com\github\eirslett\yarn\1.22.10\yarn-1.2…

ASP.NET Core----基础学习04----Model模型的创建 服务的注入

文章目录 1. 创建Models文件夹&#xff0c;3个文件的内容如下&#xff1a;&#xff08;1&#xff09;模型的创建&#xff08;2&#xff09;服务的注入 1. 创建Models文件夹&#xff0c;3个文件的内容如下&#xff1a; &#xff08;1&#xff09;模型的创建 模型的基础类Student…

Apache Hadoop完全分布式集群搭建指南

Hadoop发行版本较多&#xff0c;Cloudera版本&#xff08;Cloudera’s Distribution Including Apache Hadoop&#xff0c;简称CDH&#xff09;收费版本通常用于生产环境&#xff0c;这里用开源免费的Apache Hadoop原始版本。 下载&#xff1a;Apache Hadoop 版本下载&#x…

[Unity入门01] Unity基本操作

参考的傅老师的教程学了一下Unity的基础操作&#xff1a; [傅老師/Unity教學] Unity3D基礎入門 [華梵大學] 遊戲引擎應用基礎(Unity版本) Class#01 移动&#xff1a;鼠标中键旋转&#xff1a;鼠标右键放大&#xff1a;鼠标滚轮飞行模式&#xff1a;右键WASDQEFocus模式&…

基于模型预测控制的PMSM系统速度环控制理论推导及仿真搭建

模型预测控制&#xff08;Model Predictive Control, MPC&#xff09;是一种先进的控制策略&#xff0c;广泛应用于工业控制中。它可以看作是一种最优控制方法&#xff0c;利用对象的动态模型来预测其状态的未来行为&#xff0c;并根据每个采样时间点特定性能目标函数的优化来确…

初见:AntDB智能运维“三剑客“之ACC

前情回顾 在前两个章节中&#xff0c;我们介绍了 AntDB 智能运维"三剑客"的 ADC 和 MTK。 初见&#xff1a;AntDB智能运维"三剑客"之ADC 初见&#xff1a;AntDB智能运维"三剑客"之MTK 本文将继续介绍 AntDB 数据库智能运维平台 ACC。 AntDB 介绍…

Open3D 删除点云中重叠的点(方法一)

目录 一、概述 二、代码实现 三、实现效果 3.1原始点云 3.2处理后的点云 3.3计算结果 一、概述 在点云处理中&#xff0c;重叠点&#xff08;即重复点&#xff09;可能会对数据分析和处理的结果产生负面影响。因此&#xff0c;删除重叠点是点云预处理中常见且重要的步骤。…

时序分析基本概念介绍——SI/crosstalk/delta delay/noise/timing Window

文章目录 前言一、Crosstalk1. Crosstalk Delay Effects2. Crosstalk Noise Effects 二、Crosstalk Analysis1. Crosstalk Delay Analysis2. Crosstalk Noise Analysis 三、如何 fix delta delay 和 noise violations1. 检查delta delay 和 noisedelta delay checknoise check …

EtherCAT转Profinet网关配置说明第三讲:博图配置

EtherCAT协议转Profinet协议网关模块&#xff08;XD-ECPNS20&#xff09;是实现EtherCAT协议和Profinet协议之间无缝通讯的重要设备。使EtherCAT协议和Profinet协议能够相互转换&#xff0c;进行工控自动化里的互连和传送数据。 EtherCAT作为一种高性能实时以太网通信协议&…

yum install epel-release 遇到的问题

问题&#xff1a; 安装epel的时候,执行 yum install -y epel-release 报错“Could not retrieve mirrorlist http://mirrorlist.centos.org/?release7&archx86_64&repoos&infrastock error was 14: curl#6 - "Could not resolve host: mirrorlist.centos.…

在VMware虚拟机的创建以及安装linux操作系统

一、创建虚拟机 1.双击打开下载好的VMware Workstation软件 2.点击“创建新的虚拟机” 3.根据个人选择需要创建的虚拟机&#xff0c;点击下一步 4.直接点击下一步 5.选择稍后安装操作系统&#xff0c;点击下一步 、 6.选择需要的操作系统&#xff0c;点击下一步 7.根据…

分享一些提升效率的办公、学习神器!

分享一些提升效率的办公、学习神器&#xff01; 文章目录 分享一些提升效率的办公、学习神器&#xff01; 一、 ✅ 文件搜索工具 Everything&#xff1a;1.1 Everything 主要功能&#xff1a;1.2 Everything 下载地址&#xff1a; 二、 ✅ 文件压缩解压工具 7 - Zip&#xff1a…

【TB作品】51单片机 Proteus仿真 00013红外proteus仿真循迹避障小车

实验报告&#xff1a;智能小车系统设计与实现 一、背景介绍 本实验旨在设计并实现一个基于STC89C52单片机控制的智能小车系统。该系统通过超声波传感器进行避障&#xff0c;通过红外接收器实现远程控制&#xff0c;同时具备循迹功能。整个系统的核心是单片机&#xff0c;它通…

MySQL之表的约束(1)

目录 空属性(NULL) 实例建表 插入操作 默认值(default) 建表 插入操作 NULL与default的结合 列描述 建表 zerofill 建表 插入操作 主键 建表 插入 主键的增加与去掉 去掉 增加 复合主键 插入的影响 真正约束字段的是数据类型&#xff0c;但是数据类型约束很单一&a…

阿里云 OSS - 开通到使用、服务端签名直传(前后端代码 + 效果演示)

目录 开始 OSS 相关术语须知 阿里云 OSS 开通 阿里云 OSS 使用 官方文档教程 实战开发 阿里云 OSS 自动配置 环境配置 实战开发 服务端签名直传 概述 代码实现 开始 OSS 相关术语须知 中文 英文 说明 存储空间 Bucket 存储空间是您用于存储对象&#xff08;Ob…

Transformer-LSTM预测 | Matlab实现Transformer-LSTM多变量时间序列预测

Transformer-LSTM预测 | Matlab实现Transformer-LSTM多变量时间序列预测 目录 Transformer-LSTM预测 | Matlab实现Transformer-LSTM多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现Transformer-LSTM多变量时间序列预测&#xff0c;Transf…