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声明的函数,在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数);
存在基类类型的指针或者引用,通过该指针或引用调用虚函数;
动态联编的实现机制 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++入门:多态
多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。C 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。1、纯虚函数声明如下: 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号位
拉斯维加斯袭击者(英语: Las Vegas Raiders)又译拉斯维加斯侵略者或拉斯维加斯突击者,是一支主场位于美国内华达州拉斯维加斯的职业美式橄榄球球队,属全国橄榄球联盟 (NFL) 的美国橄榄球联合会 (AFC) 西区。实际上&…...
韩顺平Linux基础学习(1)
内容概括...
Rust学习入门--【6】Rust 基础语法
Rust 基础语法 变量,数据类型,注释,函数和控制流,这些是大部分编程语言都具有的编程概念。 本节将学习理解这些概念。 变量 Rust 是强类型语言,但具有自动判断变量类型的能力。这很容易让人与弱类型语言产生混淆。…...
LINUX提权入门手册
前言 发点存货 LINUX权限简介 在学习提权之前我们先了解一下linux里面的权限我们使用命令: ls -al即可查看列出文件所属的权限: 文件头前面都有一段类似的字符,下面我们仔细分析一下里面符号分别代表什么。 -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指令固件,没有MQTT的,所以无法通过MQTT指令与云平台通信,需要烧录固件(如果测试到有MQTT相关的指令,则不用重新烧录固件) 固件烧录…...
【Kafka】【三】安装Kafka服务器
Kafka基本知识 Kafka介绍 Kafka是最初由Linkedin公司开发,是⼀个分布式、⽀持分区的(partition)、多副本的 (replica),基于zookeeper协调的分布式消息系统,它的最⼤的特性就是可以实时的处理 …...
关于适配器模式,我遗漏了什么
近期有些tasks需要 重构or适配 老的代码。 与其向上面堆💩,不如优雅的去解决。 首先我的问题在于,错误的把 堆屎的操作 ,当作了适配器模式的操作。 比如原函数入参,需要更改某个属性,把这种操作外包一层…...
SQL Serve 日志体系结构
SQL Server 事务日志记录着 undo 及 redo 日志,为了保证数据库在崩溃后恢复,或者在正常数据库操作期间进行回滚,保证数据库事务完整性和持久化。如果没有事务日志记录,数据库在事务上将不一致,并且在数据库崩溃后可能导…...
【C++1】函数重载,类和对象,引用,string类,vector容器,类继承和多态,/socket,进程信号,public,ooci
文章目录1.函数重载:writetofile(),Ctrue和false,C0和非02.类和对象:vprintf2.1 构造函数:对成员变量初始化2.2 析构函数:一个类只有一个,不允许被重载3.引用:C中&取地址&#x…...
asio网络编程 tcp、udp、rpc
轻量级的tcp/udp/rpc库,简化socket程序编写。 同时,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,将双目相机采集到任意一点的深度数据进行串口传输 一、项目说明/Overview 所实现的功能:基于Intel Realsense官方提供的SDK,双目深度相机能获取到相机任何一个像素点距离前方障碍物的距离࿰…...
jetson nano(ubuntu)安装Cmake
文章目录安装环境一.命令行安装二.Cmake源码编译安装安装环境 jetson nano 系统:4.6.1 一.命令行安装 sudo apt install cmake这种直接安装cmake的方式,其实安装的版本都太老了,这种方式不推荐 二.Cmake源码编译安装 更新一下系统软件 su…...
图的基本介绍和表示方式
图的基本介绍 为什么要有图这个基本数据结构? 我们还学习过线性表(数组、队列、链表和栈)和树,但是我们可以发现,线性表局限于一个直接前驱(就是只能有唯一一个前面的结点)和一个直接后继的(…...
本周大新闻|传微软解散工业元宇宙团队,MIT研发垂直堆叠全彩Micro LED
本周大新闻,AR方面,消息称微软解散工业元宇宙团队;德国AR公司Gixel GmbH亮相;Brilliant推出单片式附加形态AR眼镜;MIT研发垂直堆叠全彩Micro LED;谷歌XR串流正式上线。VR方面,索尼发布了PS VR2的…...
SpringMVC:拦截器(12)
拦截器1. 拦截器概念2. 拦截器入门案例2.1 环境准备2.2 拦截器开发步骤1: 创建拦截器类步骤2: 配置拦截器类步骤3: SpringMVC添加SpringMvcSupport包扫描和interceptor包扫描步骤4: 简化SpringMvcSupport的编写5 测试3. 拦截器参数解析(了解)3.1 前置处理…...
计算机网络3:HTTP1.0和HTTP1.1的区别
目录1. HTTP是什么2.HTTP1.0和HTTP1.1的区别3.名词解释(1)If-Modified-Since(IMS)、Expires(2)If-None-Match,Etag(3)If-Unmodified-Since1. HTTP是什么 超文本传输协议…...
Urho3D 编辑器说明
Urho3D编辑器是一个脚本应用程序,可以与Urho3D播放器应用程序一起运行。要开始,请执行以下任意命令:(在bin目录中)Editor.bat、Editor.sh或Urho3DPlayer Scripts/Editor.as Urho3D播放器应用程序支持的所有命令行选项…...
C++类基础(十一)
运算符重载(二) ● 对称运算符通常定义为非成员函数以支持首个操作数的类型转换 struct Str {int val 0;Str(int input): val(input){}auto operator(Str x){std::cout << "auto operator(Str x)\n";return Str(val x.val);} }; int …...
Windows安装系列:SVN Server服务
一、下载与安装 1、下载VisualSVN-Server-5.1.1-x64.msi 地址:Download | VisualSVN Server 2、找到最新版本SVN 5.1.1,直接双击它,弹出如下安装界面 3、点击Next 4、勾选我接受, 点击"Next" 5、默认选项,…...
快速傅里叶算法(FFT)快在哪里?
目录 前言 1、DFT算法 2、FFT算法 2.1 分类 2.2 以基2 DIT(时间抽取) FFT 算法为例 2.2.1 一次分解 2.2.2 多次分解 参考 前言 对信号分析的过程中,为了能换一个角度观察问题,很多时候需要把时域信号波形变换到频域进行分…...
利用Markdown写学术论文资料汇总贴
1是最详细的,重点看! Markdown 写作,Pandoc 转换:我的纯文本学术写作流程 2补充一些细节,也可以看看。 用Markdown写作学术论文 3写得和上面差不多,如果上面两篇有什么问题还没解决,可以看看…...
MySQL 高级查询
目录1.左关联2.右关联3.子查询4.联合查询5.分组查询1.左关联 MySQL中的左关联(Left Join)是一种基于共同列的连接操作, 它将左侧表中的所有行与右侧表中匹配的行结合在一起, 如果右侧表中没有匹配的行,则结果集中右侧…...
JavaSE学习day4_01 循环for,while,do...while
1. 循环高级 1.1 无限循环 for、while、do...while都有无限循环的写法。 最为常用的是while格式的。 因为无限循环是不知道循环次数的,所以用while格式的 代码示例: while(true){} 1.2 跳转控制语句(掌握) 跳转控制语句&…...
C/C++中的static关键字
概述在C/C中都有static关键字的使用,可以分别修饰变量和函数,分为静态变量【静态成员】、静态成员函数。2. static用法概况静态变量的作用范围在一个文件内,程序开始时分配空间,结束时释放空间,默认初始化为0ÿ…...
67 自注意力【动手学深度学习v2】
67 自注意力【动手学深度学习v2】 深度学习学习笔记 学习视频:https://www.bilibili.com/video/BV19o4y1m7mo/?spm_id_fromautoNext&vd_source75dce036dc8244310435eaf03de4e330 给定长为n 的序列,每个xi为长为d的向量,自注意力将xi 既当…...
达州住房和城乡建设部网站/杭州网站排名提升
2019独角兽企业重金招聘Python工程师标准>>> grep -i 默认情况下,grep命令对大小写是敏感的,-i 选项则相反。转载于:https://my.oschina.net/doctor2014/blog/412489...
要想用谷歌访问外国网站怎么做/什么叫网络营销
📢前言🌲原题样例🌻C#方法:深度优先搜索🌻Java 方法一:深度优先搜索🌻Java 方法二:广度优先搜索💬总结🚀往期优质文章分享📢前言 🚀 算…...
怀远建设局门户网站/今日头条最新版
单例模式通常用于保证系统中一个类只有一个单例。 单例模式分为三种:懒汉式、饿汉式、双重锁模式 例1:懒汉式(会产生线程安全问题,需要使用synchronized关键字进行加锁,只有在使用单例模式的时候,实例对象才会被创建) …...
竞拍网站开发/网站推广的方式
项目介绍 旅游自主系统一个Android 客户端JSP Servlet服务端应用程序,启动Android上的应用程序后可以查看信息等。Android客户端上的信息数据是通过后台JSP Servlet服务端应用程序获取的,这个后台服务可以根据客户端发出的请求,返回信息。 图…...
网站新手引导怎么做/十大软件免费下载网站排行榜
一单选题 1 i最后等于多少() int i 1;int j i;if((i>j)&&(i j)) ij; 占坑 4.4补...
网站 app开发 财务做帐/seo一个关键词多少钱
len 获取容器类型的元素个数, 或者说获取容器的长度 str1 123 list1 [1, 2, 3] tuple1 (1, 2, 3) set1 {1, 2, 3} dict1 {name: 123, age: 18} 使用len可以获取list str tuple set中的元素个数 print(len(str1)) print(len(list1)) print(len(tuple1)) print(len(set1)…...