C++中多态的原理【精华】

虚函数表

通过一道题我们先感受一下编译器针对多态的处理

#include <iostream>
using namespace std;class Base
{
public:virtual void Func1(){cout << "Func1()" << endl;}
private:int _b = 1;char _c
};int main()
{cout << sizeof(Base) << endl;return 0;
}

在x64环境下,显示的结果是12字节
在这里插入图片描述

为什么是12字节呢?一个int就4字节,一个char就1字节,内存对齐一下也是8字节呀!为什么显示的结果是12字节呢? 我们调试代码,看看内部结构
在这里插入图片描述
通过调试我们发现Base创建的对象里面有一个指针_vfptr,如果我们计算sizeof的时候把这个指针算上的话刚刚好的12字节!

那么疑问来了,这个指针到底是什么?为什么会出现在对象里面?这个指针到底有什么作用?

这个指针我们叫做虚函数表指针(v代表virtual,f代表function)。一个含有虚函数的类中都至少都有一个虚函数表指针,因为虚函数的地址要被放到虚函数表中,虚函数表也简称虚表,。那么子类中这个表放了些什么呢?我们接着往下分析

#include <iostream>
using namespace std;class Base
{
public:virtual void Func1(){cout << "Func1()" << endl;}virtual void Func2(){cout << "Func2()" << endl;}void Func3(){cout << "Func3()" << endl;}
private:int _b = 1;char _c;
};int main()
{cout << sizeof(Base) << endl;Base b;return 0;
}

通过监视窗口再来看:
在这里插入图片描述
我们发现这个指针指向一个数组(虚函数表),这个数组(表)里面存的就是虚函数的地址


知道了包含虚函数的类里面会出现一个指针,这个指针指向一个指针数组,数组里面保存的是类里面的虚函数,接下来我们看看多态的原理

文章目录

  • 虚函数表
  • 多态的原理


多态的原理

提示:这里可以添加本文要记录的大概内容:

class Person {
public:virtual void BuyTicket() { cout << "买票-全价" << endl; }virtual void func(){}
private:int _a = 1; 
};class Student : public Person {
public:virtual void BuyTicket() { cout << "买票-半价" << endl; }
private:int _b = 0; 
};void Func(Person& p)
{p.BuyTicket();
}int main()
{Person p;Student s;Func(p);Func(s);return 0;
}

我们看一下父类的虚表指针
在这里插入图片描述
我们看到Person对象里面的_vfptr指向的指针数组里面有两个指针,说明保存的是两个地址,我们看看这两个地址是什么?
在这里插入图片描述
然后我们看一下_vfptr指针指向的数组里面保存的地址
在这里插入图片描述
再看一下子类的虚表指针
在这里插入图片描述
虚函数需要被重写,一开始子类会将虚函数进行直接拷贝,重写虚函数之后,虚函数的地址就发生改变了

那为什么多态的原理和指向的对象有关?和虚表有什么关系?

在这里插入图片描述

父类对象找到虚函数表的地址,在表里面找到虚函数的地址,因为这里是父类对象,直接调用父类对象的虚函数
子类对象赋值给父类对象,这样会产生“切片”,找到子类中父类的那一部分,寻找到虚函数表的地址,但是虚函数表里存的是子类重写的父类虚函数的地址,所以此时_vfptr指向的其实是子类的虚函数指针数组,自认而然掉用的是子类的虚函数

那为什么不使用指针和引用后,就不构成多态了呢?

#include <iostream>
#include <string>
#include <vector>
using namespace std;class Person {
public:virtual void BuyTicket() { cout << "买票-全价" << endl; }virtual void func() {}
private:int _a = 1;
};class Student : public Person {
public:virtual void BuyTicket() { cout << "买票-半价" << endl; }
private:int _b = 0;
};void Func(Person p)
{p.BuyTicket();
}int main()
{Person p;Student s;Func(p);Func(s);return 0;
}

在这里插入图片描述

因为指针和引用是指向子类对象切割出来的父类对象的那一部分
不使用指针和引用后,直接将子类传递给父类,切割出来的子类对象中父类的那一部分,成员拷贝给父类,但是不会拷贝虚表指针

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智能井盖是什么?万宾科技智能井盖传感器有什么特点

智能井盖是一种基于物联网和人工智能技术的新型城市设施。它不仅具备传统井盖的功能&#xff0c;还能通过数字化、自动化的方式实现远程监控和智能管理&#xff0c;提升城市运行效率和服务水平。 WITBEE万宾智能井盖传感器EN100-C2是一款井盖异动监测的传感终端。对窨井盖状态(…

JVMGC复习

TLAB:默认给每一个线程开辟一块内存空间存放线程自己的对象 Class对象是存放在堆区的&#xff0c;不是方法区&#xff0c;类的元数据元数据并不是类的Class对象&#xff0c;Class对象是加载的最终产品&#xff0c;类的方法代码&#xff0c;变量名&#xff0c;方法名&#xff0c…

持续集成工具jenkins操作

安装Jenkins 下载jenkins安装包 linux上下载jenkins失败 开始在windows上安装jenkins 1、先安装JDK https://jingyan.baidu.com/article/fdbd4277dd90f0b89e3f489f.html 免安装版本JDK只需要解压配置环境变量即可 2、安装Jenkins 参考文档&#xff1a; https://www.cnb…

ELK 单机安装

一丶软件下载 elasticsearch: https://www.elastic.co/downloads/past-releases kibana: https://www.elastic.co/downloads/past-releases 选择对应的版本的下载即可 二、es 安装es比较简单 rpm -ivh elasticsearch-2.4.2.rpm 修改配置文件 /etc/elasticsearch/elas…

使用 Typhoeus 和 Ruby 编写的爬虫程序

以下是一个使用 Typhoeus 和 Ruby 编写的爬虫程序&#xff0c;用于爬取 &#xff0c;同时使用了 jshk.com.cn/get_proxy 这段代码获取代理&#xff1a; #!/usr/bin/env rubyrequire typhoeus require jsondef get_proxyurl "https://www.duoip.cn/get_proxy"respon…

Jmeter —— jmeter参数化实现

jmeter参数化 在实际的测试工作中&#xff0c;我们经常需要对多组不同的输入数据&#xff0c;进行同样的测试操作步骤&#xff0c;以验证我们的软件的功能。这种测试方式在业界称为数据驱动测试&#xff0c; 而在实际测试工作中&#xff0c;测试工具中实现不同数据输入的过程称…

docker 配置mongoDB

## 拉取镜像 docker pull mongo## 设置默认账号密码 test:test 默认数据 test docker run -d --name mongo-container -e MONGO_INITDB_ROOT_USERNAMEtest -e MONGO_INITDB_ROOT_PASSWORDtest -e MONGO_INITDB_DATABASEtest -p 27017:27017 mongo

003数据安全传输-多端协议传输平台:Protobuf - 部署

文章目录 一、Windows环境二、Linux Centos环境三、protobuf测试3.1 新建.proto文件生成相应的类3.2 .proto生成相应的类的使用3.3 配置VS3.4 test代码 一、Windows环境 在windows下配置&#xff0c;无论protobuf是什么版本&#xff0c;IDE和编译器的版本都要保持一致。 比如…

SpringBoot结合Druid实现SQL监控

1、前言 SpringBoot不用我多介绍了吧&#xff0c;目前后端最流行的框架。后端开发人员最基本的要求。 Druid数据库连接池&#xff0c;出自国内 ”java圣地" 阿里巴巴。 Druid是一个用于大数据实时查询和分析的高容错、高性能开源分布式系统&#xff0c;旨在快速处理大规模…

基于nodejs+vue 衣服穿搭推荐系统

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

Linux内核8. Linux内核的经典调试方式

1 内核调试以及工具总结 内核总是那么捉摸不透, 内核也会犯错, 但是调试却不能像用户空间程序那样, 为此内核开发者为我们提供了一系列的工具和系统来支持内核的调试. 内核的调试, 其本质是内核空间与用户空间的数据交换, 内核开发者们提供了多样的形式来完成这一功能. 2 用户…

第十六届中国智慧城市大会 | 国产化三维重建技术服务智慧城市建设

2023年10月13日&#xff0c;由武汉大势智慧科技有限公司、飞燕航空遥感技术有限公司主办的第十六届智慧城市大会-实景三维技术创新与应用论坛在广州成功举办。 来自实景三维、自然资源、数字孪生、AI大数据、航空遥感等多个领域的专家&#xff0c;深度分享各自的智慧城市建设经…

QT基础 柱状图

目录 1.QBarSeries 2.QHorizontalBarSeries 3.QPercentBarSeries 4.QHorizontalPercentBarSeries 5.QStackedBarSeries 6.QHorizontalStackedBarSeries 从上图得知柱状的基类是QAbstractBarSeries&#xff0c;派生出来分别是柱状图的水平和垂直类&#xff0c;只是类型…

BAT030:按列表名单将路径a下的文件夹批量复制到路径b

引言&#xff1a;编写批处理程序&#xff0c;实现按列表名单将路径a下的文件夹批量复制到路径b。 一、新建Windows批处理文件 参考博客&#xff1a; CSDNhttps://mp.csdn.net/mp_blog/creation/editor/132137544 二、写入批处理代码 1.右键新建的批处理文件&#xff0c;点击…

分布式微服务技术栈-SpringCloud<Eureka,Ribbon,nacos>

微服务技术栈 一、微服务 介绍了解1 架构结构案例与 springboot 兼容关系拆分案例拆分服务拆分-服务远程调用 2 eureka注册中心Eureka-提供者与消费者Eureka-eureka原理分析Eureka-搭建eureka服务Eureka-服务注册Eureka-服务发现 3 Ribbon组件 负载均衡Ribbon-负载均衡原理Ribb…

浅谈压力测试的重要目标及意义

随着互联网应用的快速发展&#xff0c;软件系统的稳定性和性能成为了用户和企业关注的焦点。用户期望应用程序能够在高负载下依然保持稳定和高效。为了满足这一需求&#xff0c;压力测试成为了不可或缺的一环。本文将探讨压力测试的重要性以及如何进行压力测试。 一、压力测试的…

大数据中间件——Kafka

Kafka安装配置 首先我们把kafka的安装包上传到虚拟机中&#xff1a; 解压到对应的目录并修改对应的文件名&#xff1a; 首先我们来到kafka的config目录&#xff0c;我们第一个要修改的文件就是server.properties文件&#xff0c;修改内容如下&#xff1a; # Licensed to the …

分类预测 | MATLAB实现基于BiLSTM-AdaBoost双向长短期记忆网络结合AdaBoost多输入分类预测

分类预测 | MATLAB实现基于BiLSTM-AdaBoost双向长短期记忆网络结合AdaBoost多输入分类预测 目录 分类预测 | MATLAB实现基于BiLSTM-AdaBoost双向长短期记忆网络结合AdaBoost多输入分类预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.MATLAB实现基于BiLSTM-…

在中国,技术到底有多有用?

&#x1f64c;秋名山码民的主页 &#x1f602;oi退役选手&#xff0c;Java、大数据、单片机、IoT均有所涉猎&#xff0c;热爱技术&#xff0c;技术无罪 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; 获取源码&#xff0c;添加WX 目录 前言1.…

【四:Spring整合Junit】

目录 相同点不同点1、导入依赖增加2、编写的位置不同。。路径一定要与实现类一致 相同点 前面都一样和Spring整合mybatis&#xff08;基于注解形式&#xff09;一样Spring整合Mybatis 不同点 1、导入依赖增加 <!-- 单元测试 --><dependency><groupId>junit&…