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

C++入门:多态

多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。

C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。

1、纯虚函数声明如下: virtual void funtion1()=0; 纯虚函数一定没有定义,纯虚函数用来规范派生类的行为,即接口。包含纯虚函数的类是抽象类,抽象类不能定义实例,但可以声明指向实现该抽象类的具体类的指针或引用。

2、虚函数声明如下:virtual ReturnType FunctionName(Parameter) 虚函数必须实现,如果不实现,编译器将报错,错误提示为:

error LNK****: unresolved external symbol "public: virtual void __thiscall ClassName::virtualFunctionName(void)"

3、对于虚函数来说,父类和子类都有各自的版本。由多态方式调用的时候动态绑定。

4、实现了纯虚函数的子类,该纯虚函数在子类中就变成了虚函数,子类的子类即孙子类可以覆盖该虚函数,由多态方式调用的时候动态绑定。

5、虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数。

6、在有动态分配堆上内存的时候,析构函数必须是虚函数,但没有必要是纯虚的。

7、友元不是成员函数,只有成员函数才可以是虚拟的,因此友元不能是虚拟函数。但可以通过让友元函数调用虚拟成员函数来解决友元的虚拟问题。

8、析构函数应当是虚函数,将调用相应对象类型的析构函数,因此,如果指针指向的是子类对象,将调用子类的析构函数,然后自动调用基类的析构函数。

C++多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数;

形成多态必须具备三个条件:

1、必须存在继承关系;

2、继承关系必须有同名虚函数(其中虚函数是在基类中使用关键字Virtual声明的函数,在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数);

  1. 存在基类类型的指针或者引用,通过该指针或引用调用虚函数;

动态联编的实现机制 VTABLE

编译器对每个包含虚函数的类创建一个虚函数表VTABLE,表中每一项指向一个虚函数的地址,即VTABLE表可以看成一个函数指针的数组,每个虚函数的入口地址就是这个数组的一个元素。

每个含有虚函数的类都有各自的一张虚函数表VTABLE。每个派生类的VTABLE继承了它各个基类的VTABLE,如果基类VTABLE中包含某一项(虚函数的入口地址),则其派生类的VTABLE中也将包含同样的一项,但是两项的值可能不同。如果派生类中重载了该项对应的虚函数,则派生类VTABLE的该项指向重载后的虚函数,如果派生类中没有对该项对应的虚函数进行重新定义,则使用基类的这个虚函数地址。

在创建含有虚函数的类的对象的时候,编译器会在每个对象的内存布局中增加一个vptr指针项,该指针指向本类的VTABLE。在通过指向基类对象的指针(设为bp)调用一个虚函数时,编译器生成的代码是先获取所指对象的vtb1指针,然后调用vtb1所指向类的VTABLE中的对应项(具体虚函数的入口地址)。

当基类中没有定义虚函数时,其长度=数据成员长度;派生类长度=自身数据成员长度+基类继承的数据成员长度;

当基类中定义虚函数后,其长度=数据成员长度+虚函数表的地址长度;派生类长度=自身数据成员长度+基类继承的数据成员长度+虚函数表的地址长度。

包含一个虚函数和几个虚函数的类的长度增量为0。含有虚函数的类只是增加了一个指针用于存储虚函数表的首地址。

派生类与基类同名的虚函数在VTABLE中有相同的索引号(或序号)。

虚函数这里说的有些乱,因为 C++ 写法奇葩略多。其实可以简单理解。

虚函数可以不实现(定义)。不实现(定义)的虚函数是纯虚函数。

在一个类中如果存在未定义的虚函数,那么不能直接使用该类的实例,可以理解因为未定义 virtual 函数,其类是抽象的,无法实例化。将报错误:

undefined reference to `vtable for xxx'

这和其它语言的抽象类,抽象方法是类似的——我们必须实现抽象类,否则无法实例化。(virtual 和 abstract还是有些区别的)

也就是说,如果存在以下代码:

using namespace std;class Base {
public:virtual void tall();
};class People : Base {
public:void tall() {cout << "people" << endl;};
};

那么,在 main 方法中,我们不能使用 Base base; 这行代码,此时的 tall 没有实现,函数表(vtable)的引用是未定义的,故而无法执行。但我们可以使用 People people; 然后 people.tall();(&people)->tall(); 因为People实现或者说重写、覆盖了 Base 的纯虚方法 tall(),使其在 People 类中有了定义,函数表挂上去了,于是可以诞生实例了。

int main() {
//    Base base;//不可用People people;//可用people.tall();(&people)->tall();return 0;

上述的是针对虚函数而言,普通的函数,即使我们只声明,不定义,也不会产生上述不可用的问题。

父类的虚函数或纯虚函数在子类中依然是虚函数。有时我们并不希望父类的某个函数在子类中被重写,在 C++11 及以后可以用关键字 final 来避免该函数再次被重写。

例:

#include<iostream>
using namespace std;
class Base
{public:virtual void func(){cout<<"This is Base"<<endl;}
};
class _Base:public Base
{public:void func() final//正确,func在Base中是虚函数{cout<<"This is _Base"<<endl;}
};
class __Base:public _Base
{
/*    public://不正确,func在_Base中已经不再是虚函数,不能再被重写void func(){cout<<"This is __Base"<<endl;}*/
};
int main()
{_Base a;__Base b;Base* ptr=&a;ptr->func();ptr=&b;_Base* ptr2=&b;    ptr->func();ptr2->func();
}

以上程序运行结果:

This is _Base
This is _Base
This is _Base

如果不希望一个类被继承,也可以使用 final 关键字。

格式如下:

class Class_name final
{...
};

则该类将不能被继承。

相关文章:

C++入门:多态

多态按字面的意思就是多种形态。当类之间存在层次结构&#xff0c;并且类之间是通过继承关联时&#xff0c;就会用到多态。C 多态意味着调用成员函数时&#xff0c;会根据调用函数的对象的类型来执行不同的函数。1、纯虚函数声明如下&#xff1a; virtual void funtion1()0; 纯…...

华为OD真题_工位序列统计友好度最大值(100分)(C++实现)

题目描述 工位由序列F1,F2…Fn组成,Fi值为0、1或2。其中0代表空置,1代表有人,2代表障碍物。 1、某一空位的友好度为左右连续老员工数之和 2、为方便新员工学习求助,优先安排友好度高的空位 给出工位序列,求所有空位中友好度的最大值。 输入描述 第一行为工位序列:F1,F…...

[ruby on rails]MD5、SHA1、SHA256、Base64、aes-128-cbc、aes-256-ecb

md5 puts Digest::MD5.hexdigest(admin) sha1 require digest/sha1 puts Digest::SHA1.hexdigest(admin)base64 require base64 code Base64.encode64(admin) source Base64.decode64(code)aes-128-cbc # base64 解密数据 session_key Base64.decode64(session_ke…...

《NFL星计划》:拉斯维加斯突袭者·橄榄1号位

拉斯维加斯袭击者&#xff08;英语&#xff1a; Las Vegas Raiders&#xff09;又译拉斯维加斯侵略者或拉斯维加斯突击者&#xff0c;是一支主场位于美国内华达州拉斯维加斯的职业美式橄榄球球队&#xff0c;属全国橄榄球联盟 (NFL) 的美国橄榄球联合会 (AFC) 西区。实际上&…...

韩顺平Linux基础学习(1)

内容概括...

Rust学习入门--【6】Rust 基础语法

Rust 基础语法 变量&#xff0c;数据类型&#xff0c;注释&#xff0c;函数和控制流&#xff0c;这些是大部分编程语言都具有的编程概念。 本节将学习理解这些概念。 变量 Rust 是强类型语言&#xff0c;但具有自动判断变量类型的能力。这很容易让人与弱类型语言产生混淆。…...

LINUX提权入门手册

前言 发点存货 LINUX权限简介 在学习提权之前我们先了解一下linux里面的权限我们使用命令: ls -al即可查看列出文件所属的权限&#xff1a; 文件头前面都有一段类似的字符&#xff0c;下面我们仔细分析一下里面符号分别代表什么。 -rw-r--r-- 1 root root 第一个符号-的…...

MSI_MSI-X中断之源码分析

MSI_MSI-X中断之源码分析 文章目录MSI_MSI-X中断之源码分析一、 怎么发出MSI/MSI-X中断1.1 在RK3399上体验1.1.1 安装工具1.1.2 查看设备MSI-X信息1.1.3 验证MSI-X信息二、 怎么使用MSI/MSI-X三、 MSI/MSI-X中断源码分析3.1 IRQ Domain创建流程3.1.1 GIC3.1.2 ITS3.1.3 PCI MSI…...

Docker--consul

目录 前言 一、Consul 简介 1.1、 consul 概述 1.2 、consul 的两种模式 1.3、consul 提供的一些关键特性 二、Consul 容器服务更新与发现 三、consul 部署 3.2、查看集群信息 四、registrator服务器 consul-template 五、consul 多节点 前言 服务注册与发现是微服…...

ESP-01S使用AT指令连接阿里云

ESP-01S使用AT指令连接阿里云 烧录MQTT AT固件 出厂的ESP-01S是基本的AT指令固件&#xff0c;没有MQTT的&#xff0c;所以无法通过MQTT指令与云平台通信&#xff0c;需要烧录固件&#xff08;如果测试到有MQTT相关的指令&#xff0c;则不用重新烧录固件&#xff09; 固件烧录…...

【Kafka】【三】安装Kafka服务器

Kafka基本知识 Kafka介绍 Kafka是最初由Linkedin公司开发&#xff0c;是⼀个分布式、⽀持分区的&#xff08;partition&#xff09;、多副本的 &#xff08;replica&#xff09;&#xff0c;基于zookeeper协调的分布式消息系统&#xff0c;它的最⼤的特性就是可以实时的处理 …...

关于适配器模式,我遗漏了什么

近期有些tasks需要 重构or适配 老的代码。 与其向上面堆&#x1f4a9;&#xff0c;不如优雅的去解决。 首先我的问题在于&#xff0c;错误的把 堆屎的操作 &#xff0c;当作了适配器模式的操作。 比如原函数入参&#xff0c;需要更改某个属性&#xff0c;把这种操作外包一层…...

SQL Serve 日志体系结构

SQL Server 事务日志记录着 undo 及 redo 日志&#xff0c;为了保证数据库在崩溃后恢复&#xff0c;或者在正常数据库操作期间进行回滚&#xff0c;保证数据库事务完整性和持久化。如果没有事务日志记录&#xff0c;数据库在事务上将不一致&#xff0c;并且在数据库崩溃后可能导…...

【C++1】函数重载,类和对象,引用,string类,vector容器,类继承和多态,/socket,进程信号,public,ooci

文章目录1.函数重载&#xff1a;writetofile()&#xff0c;Ctrue和false&#xff0c;C0和非02.类和对象&#xff1a;vprintf2.1 构造函数&#xff1a;对成员变量初始化2.2 析构函数&#xff1a;一个类只有一个&#xff0c;不允许被重载3.引用&#xff1a;C中&取地址&#x…...

asio网络编程 tcp、udp、rpc

轻量级的tcp/udp/rpc库&#xff0c;简化socket程序编写。 同时&#xff0c;RPC部分也提供了方便易用的功能。 仓库地址 https://github.com/shuai132/asio_net asio_net a Tiny Async TCP/UDP/RPC library based on ASIO and RpcCore Features 简化TCP、UDP相关程序的编写…...

双目测距------双目相机V1.0,将双目相机采集到任意一点的深度数据进行串口传输(带源码)

Depth2Uart 双目测距------双目相机V1.0&#xff0c;将双目相机采集到任意一点的深度数据进行串口传输 一、项目说明/Overview 所实现的功能&#xff1a;基于Intel Realsense官方提供的SDK&#xff0c;双目深度相机能获取到相机任何一个像素点距离前方障碍物的距离&#xff0…...

jetson nano(ubuntu)安装Cmake

文章目录安装环境一.命令行安装二.Cmake源码编译安装安装环境 jetson nano 系统&#xff1a;4.6.1 一.命令行安装 sudo apt install cmake这种直接安装cmake的方式&#xff0c;其实安装的版本都太老了&#xff0c;这种方式不推荐 二.Cmake源码编译安装 更新一下系统软件 su…...

图的基本介绍和表示方式

图的基本介绍 为什么要有图这个基本数据结构? 我们还学习过线性表&#xff08;数组、队列、链表和栈&#xff09;和树&#xff0c;但是我们可以发现&#xff0c;线性表局限于一个直接前驱&#xff08;就是只能有唯一一个前面的结点&#xff09;和一个直接后继的&#xff08;…...

本周大新闻|传微软解散工业元宇宙团队,MIT研发垂直堆叠全彩Micro LED

本周大新闻&#xff0c;AR方面&#xff0c;消息称微软解散工业元宇宙团队&#xff1b;德国AR公司Gixel GmbH亮相&#xff1b;Brilliant推出单片式附加形态AR眼镜&#xff1b;MIT研发垂直堆叠全彩Micro LED&#xff1b;谷歌XR串流正式上线。VR方面&#xff0c;索尼发布了PS VR2的…...

SpringMVC:拦截器(12)

拦截器1. 拦截器概念2. 拦截器入门案例2.1 环境准备2.2 拦截器开发步骤1: 创建拦截器类步骤2: 配置拦截器类步骤3: SpringMVC添加SpringMvcSupport包扫描和interceptor包扫描步骤4: 简化SpringMvcSupport的编写5 测试3. 拦截器参数解析&#xff08;了解&#xff09;3.1 前置处理…...

《jQuery 滑动:深入浅出的探索与实践》

《jQuery 滑动&#xff1a;深入浅出的探索与实践》 引言 在Web开发中&#xff0c;滑动交互已经成为了用户操作网站、应用的重要组成部分。jQuery作为最流行的JavaScript库之一&#xff0c;提供了丰富的滑动插件和API&#xff0c;极大地简化了滑动效果的实现。本文将深入浅出地探…...

ThinkPHP高效学习路径全解析

好的&#xff0c;我们来梳理一条系统的 ThinkPHP 学习路径。ThinkPHP 是一个高效、简洁且功能丰富的 PHP 开发框架&#xff0c;学习它可以帮你快速构建 Web 应用程序。 学习路径概览 基础准备框架安装与环境配置核心概念与组件进阶功能与扩展项目实践与优化 1. 基础准备 PHP…...

通义千问2.5-7B保姆级教程:零基础5分钟本地部署,小白也能玩转AI对话

通义千问2.5-7B保姆级教程&#xff1a;零基础5分钟本地部署&#xff0c;小白也能玩转AI对话 你是不是也对那些动辄几十GB、部署复杂的AI大模型望而却步&#xff1f;觉得本地运行一个智能对话助手是件遥不可及的事情&#xff1f;今天&#xff0c;我要告诉你一个好消息&#xff…...

PyTorch梯度累积超快

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 PyTorch梯度累积的极致加速&#xff1a;从理论瓶颈到实战突破目录PyTorch梯度累积的极致加速&#xff1a;从理论瓶颈到实战突破 …...

别等被优化才醒!2026 程序员转型 AI,从 RAG 到 Agent 入门全攻略

2026年的技术圈&#xff0c;AI浪潮以席卷之势重塑产业格局&#xff0c;首当其冲受到深刻影响的&#xff0c;便是程序员群体的职业轨迹。从大厂招聘动态到中小企业的技术布局&#xff0c;一个清晰的信号正在显现&#xff1a;不懂AI的开发者&#xff0c;正在被时代快速边缘化。阿…...

Docker挂载卷修改实战:3种方法解决路径变更难题(附详细步骤)

Docker挂载卷路径变更的实战指南&#xff1a;3种高效解决方案 每次项目结构调整时&#xff0c;最让我头疼的就是那些已经配置好的Docker挂载卷路径。上周迁移服务器时&#xff0c;我不得不面对十几个容器挂载路径的调整问题。经过反复尝试和踩坑&#xff0c;我总结出三种最实用…...

vLLM部署千问72B大模型实战:从Docker镜像到API调用的完整避坑指南

vLLM实战&#xff1a;千问72B大模型高效部署与API服务优化指南 在人工智能技术快速迭代的今天&#xff0c;百亿参数级别的大模型已成为企业智能化转型的核心竞争力。如何高效部署这些"庞然大物"&#xff0c;使其在实际业务中发挥价值&#xff0c;是每个技术团队面临的…...

知识博主看过来:用AIVideo将复杂概念变成生动解说视频

知识博主看过来&#xff1a;用AIVideo将复杂概念变成生动解说视频 你是不是经常遇到这样的困扰&#xff1a;精心准备的知识点&#xff0c;用文字写出来总觉得不够直观&#xff0c;想做成视频又卡在了脚本、画面、配音、剪辑这些专业门槛上&#xff1f;一个复杂的科学原理、一个…...

Qwen3-VL:30B开发实战:软件测试与质量保障体系

Qwen3-VL:30B开发实战&#xff1a;软件测试与质量保障体系 1. 引言 在AI应用开发中&#xff0c;我们往往把大部分精力放在模型训练和算法优化上&#xff0c;却容易忽视一个关键环节&#xff1a;测试与质量保障。想象一下&#xff0c;当你费尽心思部署了一个强大的多模态模型&…...

低轨卫星C语言功耗黑洞清单(含ARM Cortex-R5F异常向量表误配置导致的17mA暗电流案例)

第一章&#xff1a;低轨卫星C语言功耗的物理约束与系统级影响 低轨卫星&#xff08;LEO&#xff09;平台受限于严苛的能源预算、热管理边界和辐射环境&#xff0c;其嵌入式软件——尤其是以C语言编写的底层驱动与任务调度模块——并非仅受逻辑正确性约束&#xff0c;更直接受制…...