【第六天】c++虚函数多态
一、多态的概述
多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联(父类与子类)时,就会用到多态。
C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。
静态多态(编译时多态,早绑定):函数重载、运算符重载
动态多态(运行时多态,晚绑定):虚函数
二、虚函数
1、知识点引入
需求:设计一个算法可以操作父类派生的所有子类
算法通用:父类指针(引用)保存 子类空间地址
父类指针 保存 子类空间地址带来的问题:

原因:

解决:通过虚函数
2、虚函数的定义
定义及用法:父类成员函数前加virtual修饰,该函数即为虚函数
子类重写父类虚函数:函数名、返回值类型、参数类型个数顺序完全一致。

动态多态条件:有继承、子类重写(覆盖)父类的虚函数,父类指针 指向子类空间。
3、虚函数原理
如果一个类中的成员函数 被virtual修饰,那么这个函数就是虚函数。类就会产生一个虚函 数指针(vfptr)指向了一张虚函数表(vftable)。
如果这个类 没有涉及到继承, 这时虚函数表中 纪录及时当前类的虚函数入口地址。
Animal的类的结构:

一旦子类重写父类虚函数,就会将子类的虚函数肉蔻地址,覆盖虚函数表中原来的入口地址。
Dog的类存结构:

三、纯虚函数和抽象类
在设计时,常常希望基类仅仅作为其派生类的一个接口。并且不希望用户实际的创建一个基类的对象。所以创建一个纯虚函数允许接口中放置成员原函数,而不一定要提供一段可能对这个函数毫无意义的代码。
一个纯虚函数(pure virtual function),使得基类称为抽象类(abstract class),抽象类 必须被继承 同时 子类 必须重写 父类的所有纯虚函数,否则 子类也是抽象类。纯虚函数使用关键字virtual并在其后面加上=0。抽象类 不能实例化 对象,如果试图去实例化一个抽象类,编译器则会阻止这种操作。
虚函数不实现函数体:
class Animal
{
public://纯虚函数virtual void speak(void)=0;
};
抽象类主要的目的 是设计 类的接口:
#include <iostream>
using namespace std;
//抽象制作饮品
class AbstractDrinking{
public://烧水virtual void Boil() = 0;//冲泡virtual void Brew() = 0;//倒入杯中virtual void PourInCup() = 0;//加入辅料virtual void PutSomething() = 0;//规定流程void MakeDrink(){this‐>Boil();Brew();PourInCup();PutSomething();}
};//制作咖啡
class Coffee : public AbstractDrinking{
public://烧水virtual void Boil(){cout << "煮农夫山泉!" << endl;}//冲泡virtual void Brew(){cout << "冲泡咖啡!" << endl;}//倒入杯中virtual void PourInCup(){cout << "将咖啡倒入杯中!" << endl;}//加入辅料virtual void PutSomething(){cout << "加入牛奶!" << endl;}
};//制作茶水
class Tea : public AbstractDrinking{
public://烧水virtual void Boil(){cout << "煮自来水!" << endl;
}//冲泡virtual void Brew(){cout << "冲泡茶叶!" << endl;}//倒入杯中virtual void PourInCup(){cout << "将茶水倒入杯中!" << endl;}//加入辅料virtual void PutSomething(){cout << "加入食盐!" << endl;}
};//业务函数
void DoBussiness(AbstractDrinking* drink){drink‐>MakeDrink();delete drink;
}int main(int argc, char *argv[])
{DoBussiness(new Coffee);//new Coffee 是在堆上分配内存创建一个 Coffee 对象,然后将该对象的指针传递给 DoBussiness 函数进行处理。cout << "‐‐‐‐‐‐‐‐‐‐‐‐‐‐" << endl;DoBussiness(new Tea);return 0
}
虚函数 和纯虚函数的 区别:
虚函数:virtual修饰 有函数体 不会导致父类为抽象类。
纯虚函数:virtual修饰,=0,没有函数体 导致父类为抽象类。子类必须重写父类的所有 纯虚函数。
四、虚析构函数
构造的顺序:父类--->成员---->子类
析构的顺序:子类--->成员---->父类
虚析构:通过父类指针 释放整个子类空间。

原理:
五、纯虚析构
纯虚析构的本质是析构函数,负责释放各类的空间。而且析构函数不能被继承。 故必须为纯虚析构函数提供一个函数体,纯虚析构函数 必须在类外实现。
#pragma warning(disable:4996)
#include<iostream>
#include<string.h>
using namespace std;
class Animal
{
public://纯虚函数virtual void speak(void)=0;//纯虚析构//纯虚析构函数 必须在类外实现virtual ~Animal()=0;
};
class Dog:public Animal
{
public://子类重写父类的虚函数,本质仍是虚函数,此时关键字virtual可省void speak(void){cout << "狗在汪汪" << endl;}~Dog(){cout<<"Dog析构函数"<<endl;}
};
void test()
{Animal* p = new Dog;p->speak();delete p;}
int main(int argc, char* argv[])
{test();return 0;
}
//纯虚析构函数 必须在类外实现
Animal::~Animal()
{cout<<"Animal析构函数"<<endl;
}
虚析构 和纯虚析构的区别:
虚析构:virtual修饰,有函数体,不会导致父类为抽象类。
纯虚析构:virtual修饰,=0,函数体必须类外实现,导致父类为抽象类。
六、多态的常见问题
1、多态的分类
2、谈谈你对动态捆绑机制的理解(虚函数实现原理)
3、重载、重定义、重写的区别
4、虚函数和纯虚函数的区别
5、虚析构和纯虚析构的区别
6、虚函数的作用
7、虚析构的作用
八、重载、重定义、重写的区别
重载:同一作用域,同名函数,参数的顺序、个数、类型不同 都可以重载。函数的返回值 类型不能作为重载条件(例:函数重载、运算符重载)
重定义:有继承,子类 重定义 父类的同名函数(非虚函数), 参数顺序、个数、类型可以 不同。子类的同名函数会屏蔽父类的所有同名函数(可以通过作用域解决)
重写(覆盖):有继承,子类重写 父类的虚函数。返回值类型、函数名、参数顺序、个 数、类型都必须一致。
相关文章:
【第六天】c++虚函数多态
一、多态的概述 多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联(父类与子类)时,就会用到多态。 C 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。 静态多态&…...
CGAL::2D Arrangements-3
3.Arrangement查询 Arrangement里面最重要的查询操作是point-location,给定一个点,查找到包含这个点的Arrangement。通常情况下,point-location查询得到的结果是Arrangement的一个face,退化情况下会是一个edge,查一个…...
机器学习--K近邻算法,以及python中通过Scikit-learn库实现K近邻算法API使用技巧
文章目录 1.K-近邻算法思想2.K-近邻算法(KNN)概念3.电影类型分析4.KNN算法流程总结5.k近邻算法api初步使用机器学习库scikit-learn1 Scikit-learn工具介绍2.安装3.Scikit-learn包含的内容4.K-近邻算法API5.案例5.1 步骤分析5.2 代码过程 1.K-近邻算法思想 假如你有一天来到北京…...
Redis 使用 RDB 持久化方式的过程
定时触发: RDB 持久化是通过设置一个定时触发的机制来进行的。管理员可以配置 Redis 在经过一定时间间隔或执行了一定数量的写操作后触发 RDB 持久化。这个配置通常在 Redis 的配置文件中进行,可以通过 save 或 save 900 1 这样的配置项来设定。 save 90…...
仰暮计划|“我非常感谢党的领导,作为一名普通百姓,我也愿意为国家的发展继续贡献微薄的力量”
她出生于1945年,现居河南省平顶山市宝丰县城关镇东街社区,是一位和蔼可亲的老人。 孙奶奶回忆,在学生时期,是点蜡烛照明的,打瞌睡或者离作业本近的时候,就会烧到头发,当时的作业量不大ÿ…...
【思科ssh】思科模拟器配置ssh登录
配置路由器的名称为R1 配置路由器的域名为aaa.com 使用rsa来加密传输数据,密钥位数为2048 配置登录用户名为cj,密码为123456 只允许ssh登录,不能以其他方式登录 本地验证...
python创建pdf文件
目录 一:使用reportlab库 二:使用使pdf库 在Python中生成PDF文件可以使用多种库,其中最常用的是reportlab和fpdf。以下是使用这两个库生成PDF文件的示例代码: 一:使用reportlab库 1:写入文字信息 from r…...
ubuntu开机报错/dev/nume0n1p2:clean
TOC 一、前提 1、当你平时用的图站或者linux系统出现这个问题,首先看看你的显卡有没有换位置。 我的就是项目电脑,同事换了显卡位置,我不知道,当我在这个基础上继续做的时候,出了问题。 2、当你是第一次装显卡&…...
openstack(T版)公有云--Dashboard服务
公有云上OpenStack Train最小化安装_openstack最小化部署-CSDN博客 我的opensatck(T)是参考上面链接去部署完成的,在部署完Dashboard服务后,将要用浏览器访问的时候出现了404 500 Internal Server Error 等各种各样的问题,以下是我排查问题…...
Vue ElementUI中el-table表格嵌套样式问题
一、表格嵌套要求: 两个表格嵌套,当父表格有children数组时子表格才展示;子表格数据少于父表格展示字段,且对应固定操作列不同; 二、嵌套问题: 当使用el-table的typeexpand实现表格嵌套时,样…...
ssm+vue的校园一卡通密钥管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。
演示视频: ssmvue的校园一卡通密钥管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系…...
docker进阶 问题1
如何使用Docker的容器调试和故障排查工具? Docker提供了一系列强大的工具来帮助开发者调试和排查容器中的问题。以下是一些关键步骤和工具的使用方法: 查看容器日志:使用docker logs [容器ID或名称]命令可以轻松查看容器的标准输出和错误。…...
【OpenVINO™】在 MacOS 上使用 OpenVINO™ C# API 部署 Yolov5 (下篇)
在 MacOS 上使用 OpenVINO™ C# API 部署 Yolov5 (下篇) 项目介绍 YOLOv5 是革命性的 "单阶段"对象检测模型的第五次迭代,旨在实时提供高速、高精度的结果,是世界上最受欢迎的视觉人工智能模型,代表了Ult…...
使用CHATGPT进行论文写作的缺点和风险
为了真正感受 ChatGPT 的写作潜力,让我们先将其与传统的论文写作方法进行一下比较分析 CHATGPT论文写作的缺点和风险 传统论文写作的考验和磨难很深:费力的研究、组织想法和精心设计的逻辑论证,往往以牺牲你的理智为代价。 进入ChatGPT&am…...
【Android-Gradle】多模块开发中,定义额外属性(全局变量),穿梭在不同的Gradle文件中(kotlin脚本版)
其他信息可以参考官网:https://docs.gradle.org/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html#org.gradle.api.plugins.ExtraPropertiesExtension 但是本文讲一些简单应用: 需求1:根目录gradle文件定义一个全局变量 …...
React18原理: Fiber架构下的单线程CPU调度策略
概述 React 的 Fiber 架构, 它的整个设计思想就是去参考CPU的调度策略CPU现在都是多核多进程的,重点研究的是 CPU是单核单线程,它是如何调度的?为什么要去研究单线程的CPU? 浏览器中的JS它是单线程的JS 的执行线程和浏览器的渲染GUI 是互斥…...
个人搜集的gstreamer学习链接
gstreamer资源: GStreamer: 官方英文官网 GStreamer C开发教程 (gstreamer安装包下载目录) GStreamer GitLab源码 gstreamer 插件列表) gstreamer官方文档: https://gstreamer.freedesktop.org/documentation/tutorials/index.html?gi-languagec …...
Blazor Wasm Gitee 码云登录
目录: OpenID 与 OAuth2 基础知识Blazor wasm Google 登录Blazor wasm Gitee 码云登录Blazor SSR/WASM IDS/OIDC 单点登录授权实例1-建立和配置IDS身份验证服务Blazor SSR/WASM IDS/OIDC 单点登录授权实例2-登录信息组件wasmBlazor SSR/WASM IDS/OIDC 单点登录授权实例3-服务端…...
Android 自定义BaseActivity
直接上代码: BaseActivity代码: package com.example.custom.activity;import android.annotation.SuppressLint; import android.app.Activity; import android.content.pm.ActivityInfo; import android.os.Bundle; import android.os.Looper; impor…...
基于鲲鹏服务器的LNMP配置
基于鲲鹏服务器的LNMP配置 系统 Centos8 # cat /etc/redhat-release CentOS Linux release 8.0.1905 (Core) 卸载已经存在的旧版本的安装包 # rpm -qa | grep php #查看已经安装的PHP旧版本# rpm -qa | grep php | xargs rpm -e #卸载已经安装的旧版,如果提示有…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
