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

【C++从小白到大牛】多态那些事儿(上)

一、多态的概念

1.1概念:

通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。

二、 多态的定义及实现

 2.1多态的构成条件

多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。比如Student继承了Person。Person对象买票全价,Student对象买票半价。

在继承中要多态还要两个条件

  1. 父类指针或引用去调用虚函数,这样才能保证传父类对象调用的就是父类的虚函数,传子类对象,调用的是子类的虚函数(调用子类传子类利用切片的原理)
  2. 虚函数完成重写:父子类中的两个虚函数,三同(函数名、参数、返回值)这样父子类的两个虚函数才能构成重写

可以将重写理解为隐藏的子集,因为隐藏仅要求函数名相同

 2.2虚函数

虚函数:即被virtual修饰的类成员函数称为虚函数。

class Person {
public:virtual void BuyTicket() { cout << "买票-全价" << endl;}
};

2.3虚函数的重写

虚函数的重写(覆盖):派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的返回值类型、函数名字、参数列表完全相同),称子类的虚函数重写了基类的虚函数

class Person {
public:virtual void BuyTicket() { cout << "买票-全价" << endl; }
};
class Student : public Person {
public:virtual void BuyTicket() { cout << "买票-半价" << endl; }
/*注意:在重写基类虚函数时,派生类的虚函数在不加virtual关键字时,虽然也可以构成重写(因
为继承后基类的虚函数被继承下来了在派生类依旧保持虚函数属性),但是该种写法不是很规范,不建议这样使用*/
/*void BuyTicket() { cout << "买票-半价" << endl; }*/
};
void Func(Person& p)
{ p.BuyTicket(); }

2.4虚函数重写的两个例外:

1. 协变(基类与派生类虚函数返回值类型不同)(了解 不重要)

协变,虚函数返回值可以不同,返回值要求必须是父子类关系的指针或者引用

class A{};
class B : public A {};
class Person {
public:virtual A* f() {return new A;}
};
class Student : public Person {
public:virtual B* f() {return new B;}
};

2. 析构函数的重写(基类与派生类析构函数的名字不同)

普通调用:看指针或者引用或者对象的类型

多态调用:看指针或者引用指向的对象

我们希望上面的特殊情况是多态调用,如果是普通调用,会造成内存泄漏(student对象没有析构,如下图)。

所以我们如何才能变成多态调用呢?

在子类和基类的析构函数都加上virtual构成重写,变为多态调用。那这里违反重写的规则,函数名都不相同,怎么能构成重写呢?

答:

虽然函数名不相同,看起来违背了重写的规则,其实不然,这里可以理解为编译器对析构函数的名称做了特殊处理,编译后析构函数的名称统一处理成destructor

TIP:特殊情况

如果基类的析构函数为虚函数,此时派生类析构函数只要定义,无论是否加virtual关键字,都与基类的析构函数构成重写

2.5、关于父类子类virtual加与不加

虚函数重写时,父类虚函数加了virtual,子类不加,也构成重写;但是如果父类不加virtual,就不构成重写。

建议:两个虚函数都加上virtual

2.6 C++11 override 和 final

final 关键字的两个作用:

其一是final修饰的类是最终类,不能被继承

注意实现一个类,这个类不能被继承还有一种方法:让父类构造函数私有化,派生类实例化不出对象。

其二是修饰虚函数,表示该虚函数不能再被重写

override: 检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译就会报错。

2.7重载、覆盖(重写)、隐藏(重定义)的对比

重载:

  1. 两个函数在同一作用域
  2. 函数名相同,参数不同

重写(覆盖)

  1. 两个函数分别在基类和派生类的作用域
  2. 函数名/参数/返回值都必须相同(协变例外)
  3. 两个函数都必须是虚函数

重定义(隐藏)

  1. 两个函数分别在基类和派生类的作用域
  2. 函数名相同
  3. 两个基类和派生类的同名函数不构成重写就是重定义

四、多态的原理

4.1虚函数表

先做一道笔试题:

// 这里常考一道笔试题:sizeof(Base)是多少?
class Base
{
public:virtual void Func1(){cout << "Func1()" << endl;}
private:int _b = 1;
};

通过观察测试我们发现b对象是8bytes。

除了_b成员,还多一个__vfptr指针,也就是虚函数表指针,这个表本质上是一个函数指针的数组

vfptr是存放函数指针的数组,就是将虚函数的指针存进去。

虚函数的重写也叫做覆盖,重写是语法层的概念,覆盖是原理层的概念。

形象的记忆:

比如上图,子类将父类的拷贝过来,然后虚表重写的部分将原先父类虚表的部分进行一个覆盖

具体如何实现多态调用和普通调用?

  • 多态调用:

运行时去虚函数表中找函数的地址,进行调用,所以指向父类调用的是父类虚函数,指向子类调用的是子类虚函数。

  • 普通调用:

编译时,通过调用者类型确定函数地址。

面试题解析:

解析:

首先我们看到B继承A,那么B里面的func函数和A里面的func函数构不构成重写呢?

函数名相同,返回值相同,参数类型相同(注意看参数是否相同,就是看类型,与变量名、缺省值无关!)并且父类是虚函数,所以构成重写!

接着我们看到p->test(),直接调用到了父类test()里面的func()函数,那么这里this指针是A* or B*呢,因为此时的test()是在父类,因此是A*,(如果是B*子类,那就不满足多态的条件必须是父类,所以不满足多态)所以这里的func函数构成了多态,因此是多态调用,所以是指针/引用指向的类型,因此调用B里面的func函数,所以答案是D嘛?

但真正的答案是B。

原因是多态调用,重写是实现重写,会将父类的函数声明与子类进行组合,因此val的值就是父类的1,因此答案是B!

下面因为是子类的调用,不构成多态,因此答案全都是D

相关文章:

【C++从小白到大牛】多态那些事儿(上)

一、多态的概念 1.1概念: 通俗来说&#xff0c;就是多种形态&#xff0c;具体点就是去完成某个行为&#xff0c;当不同的对象去完成时会产生出不同的状态。 二、 多态的定义及实现 2.1多态的构成条件 多态是在不同继承关系的类对象&#xff0c;去调用同一函数&#xff0c;产…...

网站在线查询工具箱源码分享

终极网络工具系统”(SAAS)&#xff0c;是一款功能强大的PHP脚本在线查询工具。本版集合了超过470种快速且易用的Web工具&#xff0c;为日常任务处理和开发人员提供了极大的便利。作为一款综合性的网络工具系统&#xff0c;66toolkit不仅满足了用户的基本网络需求&#xff0c;更…...

SSH简写且免密登陆终端设备

问题 通常使用ssh连接远程设备时&#xff0c;需要先执行ssh <username><ip>&#xff0c;然后再输入终端设备的用户密码。比较麻烦。 解决 可以用如下方法设置命令缩写以及免密登陆&#xff1a; 免密 首先在本地生成私钥&#xff1a; ssh-keygen -t rsa # or …...

算力共享中神经网络切片和算力分配策略

目录 神经网络切片 按照算力的分布进行网络层数切片;就是算力越强,运算神经网络层数越多 神经网络切片和算力占比进行映射 算力分配策略 get_current_shard 神经网络切片 按照算力的分布进行网络层数切片;就是算力越强,运算神经网络层数越多 神经网络切片和算力占比进…...

3章4节:R的逻辑运算和矩阵运算

逻辑运算和矩阵运算是R语言中两个重要的功能模块,前者用于逻辑判断和条件筛选,后者用于处理多维数据结构和执行线性代数运算。本文章详细介绍R语言中的逻辑运算和矩阵运算,帮助读者掌握这两类运算的基本概念、操作方法和实际应用。 一、逻辑运算 逻辑运算在编程语言中扮演着…...

使用EasyAR打包安卓操作注意

EasyAR for Scene 4.6.3 丨Unity2020.3.15f2 打包Unity注意事项 一、默认渲染管线 官方参考链接&#xff1a;ARFoundation 简单注意 1.打包设置为Android平台 2.PackageName和EasyAR中保持一致 3.Scripting Backend设置为IL2CPP&#xff0c;以及设置为ARM64 4.取消Auto …...

驾驭PyCharm:破解环境配置的迷宫

驾驭PyCharm&#xff1a;破解环境配置的迷宫 PyCharm&#xff0c;作为Python开发者的首选IDE之一&#xff0c;以其强大的功能和用户友好的界面而广受好评。然而&#xff0c;即便是最强大的工具&#xff0c;环境配置问题也可能成为开发者的拦路虎。本文将带你深入探索PyCharm中…...

大数据技术原理-Hadoop的安装

摘要 随着大数据时代的到来&#xff0c;Hadoop作为一项重要的分布式计算框架&#xff0c;其安装与配置是大数据技术学习者必须掌握的技能。本文通过实验报告的形式&#xff0c;详细记录了在虚拟机环境下安装Hadoop并配置其为伪分布式模式的全过程。实验过程中&#xff0c;遇到…...

从根儿上学习spring 八 之run方法启动第四段(2)

图2 我们接着上一篇接着来看refresh方法&#xff0c;我们上一小节说完了invokeBeanFactoryPostProcessors(beanFactory)方法&#xff0c;这一节我们来看registerBeanPostProcessors(beanFactory)方法。 从方法名称定义我们就能看出这个方法主要是用来注册BeanPostProcesor的。…...

牛顿插值法代替泰勒公式

引入 例题 近似函数&#xff1a; 通过这个近似函数可以看出&#xff0c;若要证的函数超过二阶可导&#xff0c;那么就不适合用牛顿插值法代替泰勒公式 因为&#xff0c;后面的操作非常复杂&#xff0c;不划算了… 总结 我们可以通过牛顿插值法生成一个逼近曲线的直线&#xf…...

为 Laravel 提供生产模式下的容器化环境:打造现代开发环境的终极指南

为 Laravel 提供生产模式下的容器化环境&#xff1a;打造现代开发环境的终极指南 在现代开发中&#xff0c;容器化已经成为一种趋势。使用 Docker 可以让我们轻松地管理和部署应用程序。本文将带你一步步构建一个高效的 Laravel 容器化环境&#xff0c;确保你的应用程序在开发…...

Visual Studio 和 VSCode 哪个好?

​ 您好&#xff0c;我是程序员小羊&#xff01; 前言 想要对Visual Studio 和 VSCode 进行比较&#xff0c;就要充分了解Visual Studio (VS) 和 Visual Studio Code (VSCode) 各有其优势和适用场景进行分析。Visual Studio (VS) 和 Visual Studio Code (VSCode) 都是由微软开发…...

百款精选的HTML5小游戏源码,你可以下载并直接运行在你的小程序或者自己的网站上

今天我带来了一份特别的礼物——百款精选的HTML5小游戏源码&#xff0c;你可以下载并直接运行在你的小程序或者自己的网站上&#xff0c;只需双击index.html即可开始。无论你是在寻找创意引流&#xff0c;还是想为你的网站增添互动性&#xff0c;这些小游戏都能帮你实现&#x…...

01 LVS负载均衡群集

集群 在互联网应用中&#xff0c;随着站点对硬件的性能、响应速度、服务稳定性、数据可靠性等要求越来越高&#xff0c;单台服务器越来越力不从心 集群的含义 Cluster&#xff0c;集群也叫群集由多台主机构成&#xff0c;但对外只表现为一个整体 集群分类 类型 负载均衡集…...

Redis结合Lua脚本的简单使用

我们就拿购物车举例子 现在有5个东西免费送&#xff0c;我们只能选择1个 例如 可乐 美年达 香蕉 苹果 薯片 我们选择后就放进redis里面 然后我们不能选重复&#xff0c;只能选不同 Lua脚本 我们redis使用lua脚本的时候&#xff0c;会传两个参数进去 一个是List<Strin…...

Java使用zip4j加密压缩和解压文件与文件夹

最近项目中有个需求需要对文件夹进行压缩后传输&#xff0c;考虑数据泄露安全性问题&#xff0c;需要对压缩包进行加密&#xff0c;特地查找了下开源压缩加密类库&#xff0c;找到了Java语言开发的zip4j库&#xff0c;觉得挺好用的&#xff0c;在这分享给大家&#xff01; Jav…...

一款好用的开源网站内容管理系统

今天给大家介绍的是一款开源网站内容管理系统&#xff08;灵活、易用&#xff0c;性能良好、运行稳定&#xff0c;轻松管理建设网站&#xff09; 官网&#xff1a;https://www.ujcms.com/ 介绍 客户端兼容Edge&#xff08;Chromium版&#xff09;、谷歌浏览器&#xff08;Chro…...

Qt Modbus 寄存器读写实例

一.线圈状态寄存器读写 项目效果如下 1. 写单个寄存器 MODBUS_API int modbus_write_bit(modbus_t *ctx, int coil_addr, int status); int addrui->spinBoxwirte_addr->value();int dataui->spinBoxwirte_data->value();int ret modbus_write_bit(mb,addr,d…...

centos安装es、kibana、ik

这里es使用的是7.10.2版本的es&#xff0c;物料包下载地址如下 #注意安装的插件需和es版本保持一致 #es https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.10.2-linux-x86_64.tar.gz #kibana https://artifacts.elastic.co/downloads/kibana/kibana-7.10…...

调试工具之GDB的基本使用

GDB基本使用 GDB是Linux下一款非常强大的调试软件&#xff0c;其实就是GNU Debugger的缩写。接下来我们学习一下他的基本使用。 例子函数&#xff0c;其中只有一个ds18b20的采集温度函数和一个主函数&#xff1a; #include <stdio.h> #include <errno.h> #includ…...

seo网站制作如何选择合适的关键词

SEO网站制作如何选择合适的关键词 在当今互联网时代&#xff0c;一个成功的网站不仅需要精美的设计&#xff0c;还需要强大的搜索引擎优化&#xff08;SEO&#xff09;技术。其中&#xff0c;关键词选择是SEO策略中至关重要的一环。选择合适的关键词不仅能够提高网站在百度等搜…...

新手福音:在快马平台用一句话描述,AI帮你生成专属技能展示网页代码

作为一个刚入门编程的新手&#xff0c;想要展示自己的技能却无从下手&#xff1f;最近我发现了一个超级友好的工具&#xff0c;完全是为我们这种小白量身定做的。只需要简单描述需求&#xff0c;就能自动生成一个完整的个人技能展示网页项目&#xff0c;而且所有代码都带着详细…...

大模型岗位大揭秘:面试官从不说的5个秘密!

本文作者通过自身经历&#xff0c;详细解析了五大与大模型相关的岗位区别&#xff0c;包括大模型算法工程师、大模型应用工程师、云厂商解决方案架构师、云厂商大模型解决方案架构师以及云厂商FDE大模型前沿部署工程师。文章从工作重心&#xff08;模型vs客户&#xff09;、面试…...

寒武纪高级系统软件工程师面试技术解析

1. 寒武纪高级系统软件工程师面试全解析 作为一名在芯片验证领域摸爬滚打多年的工程师&#xff0c;去年我经历了寒武纪高级系统软件工程师岗位的完整面试流程。这个岗位对系统底层和芯片验证的要求非常高&#xff0c;今天我就把两轮技术面的核心问题拆解给大家&#xff0c;并分…...

我的STM32F407项目踩坑记:FreeRTOS下实现U盘OTA升级,这些细节你一定要注意

STM32F407实战&#xff1a;FreeRTOS环境下U盘OTA升级的九大陷阱与解决方案 去年接手一个工业控制器项目时&#xff0c;客户突然要求增加U盘固件升级功能。本以为凭借之前的IAP开发经验能轻松搞定&#xff0c;结果在FreeRTOS环境下踩坑无数——从任务调度混乱到USB驱动冲突&…...

基于合法无代码平台滥用的新型钓鱼攻击机理与防御体系研究

摘要 2026 年 3 月卡巴斯基实验室披露针对 Bubble.io 等正规无代码开发平台的恶意滥用钓鱼攻击&#xff0c;攻击者依托平台高信誉域名、SSL 证书与可视化开发能力&#xff0c;快速生成高仿真钓鱼页面&#xff0c;绕过传统邮件网关与终端检测&#xff0c;实现账号凭证、多因素认…...

OpenClaw快速接入QQ教程

OpenClaw快速接入QQ教程 OpenClaw是一个强大的开源AI Agent&#xff0c;支持通过多种聊天软件进行交互。下面将详细介绍如何在OpenClaw中接入QQ&#xff0c;实现QQ与AI的对话操作。 前置准备工作 在开始配置之前&#xff0c;请确保完成以下准备工作&#xff1a; QQ账号部署好Op…...

通讯协议(四)——SPI通信:从时序图到模式配置的实战解析

1. SPI通信基础&#xff1a;从四线制到主从架构 第一次接触SPI通信时&#xff0c;我被它简洁的物理连接方式惊艳到了。相比其他通信协议&#xff0c;SPI只需要四根线就能实现全双工通信&#xff0c;这让电路设计变得异常清爽。MISO&#xff08;主入从出&#xff09;、MOSI&…...

图网络梯度计算与反向传播:自动微分技术的完整指南

图网络梯度计算与反向传播&#xff1a;自动微分技术的完整指南 【免费下载链接】graph_nets Build Graph Nets in Tensorflow 项目地址: https://gitcode.com/gh_mirrors/gr/graph_nets 在深度学习领域&#xff0c;图网络&#xff08;Graph Networks&#xff09;凭借其处…...

颈椎病反复复发?终于找到根源解决办法

颈椎疼治好了又犯&#xff0c;花钱不少、遭罪不少&#xff0c;到底为啥&#xff1f;核心就两点&#xff1a;只止疼不修病灶、纤维环破裂没修复。 普通治疗只能暂时推开压迫&#xff0c;髓核还会再次突出&#xff0c;神经反复受刺激&#xff0c;酸痛麻木永远断不了根。长春颈椎腰…...