多态--下
文章目录
- 概念
- 多态如何实现的指向谁调谁?
- 例子
- 分析
- 含有虚函数类的大小是多少?
- 虚函数地址
- 虚表地址
- 多继承的子类的大小怎么计算?
- 练习题
- 虚函数和虚继承
概念
优先使用组合、而不是继承;
继承会破坏父类的封装、因为子类也可以调用到父类的函数;
子类必须实现父类的纯虚函数;
内联函数没有地址,他是直接在定义的地方展开。所以不能是虚函数、虚函数是要有地址的;
虚函数不能是static函数,因为没有this指针、等于说是全局的,虚表要的是对象里面的;
普通函数继承是实现继承,就是不去重写父类的函数体,直接用的;虚函数的继承目的就是要重写这个函数体,自改成自己想要的;
虚函数在编译阶段就生成了,并且存在代码段;
析构函数最好写成多态。多态就是指向谁调谁,这样子类就可以调用自己的析构函数
构造函数不能写成多态;因为对象中的虚表指针实在初始化列表时开始初始化的;
多态如何实现的指向谁调谁?
虚函数的地址存在虚函数表中,通过虚函数表来调用虚函数;
同类型的对象共用一个虚表;
子类不重写父类的虚函数,也是和父类共用同一张虚表;重写就不会共用虚表
例子
#define _CRT_SECURE_NO_WARNINGS#include <iostream>
using namespace std;class person
{
public:virtual void BuyTicket(){cout << "成人票" << endl;}
};class student : public person
{
public:virtual void BuyTicket(){cout << "学生票" << endl;}
};void buy(person& b)
{b.BuyTicket();
}int main()
{student s;person p;buy(s);buy(p);return 0;
}
分析
1、子类继承后,虚函数表是一样的,重写后就把虚函数表copy出来换一个地址,把新的内容覆盖了;

2、调用时传过去的参数累心是谁的就指向谁的虚函数表,s是student类型那就是用student里面的函数;

2、子类虚函数不重写会怎样
如果不重写,那父级和子级虚函数表的地址是相同的

含有虚函数类的大小是多少?
普通函数不占空间,虚函数有个指针、所以站指针的大小空间,32位的4字节、64位的8字节;
在类里面:虚函数占一个指针的大小,不管有多少个虚函数就只占一个指针的大小;对象里面只是存了一个指针指向这个虚表
虚表的大小才要看有几个虚函数;
多继承的子类,继承了几个父类就有几个父类的指针大小
如下就一个虚函数64位

计算方法和结构体其实一样,内存对齐
加了一个int变量,理应8+4 = 12,但是最小对齐数为8,类的大小是其成员最小对齐数的整数倍;所以是16;

虚函数地址
#define _CRT_SECURE_NO_WARNINGS#include <iostream>
using namespace std;class person
{
public:virtual void BuyTicket(){cout << "成人票" << endl;}
private:int a;
};class student : public person
{
public:virtual void BuyTicket(){cout << "学生票" << endl;}
};void buy(person& b)
{b.BuyTicket();
}class base
{
public:virtual void func1(){cout << "base::func1" << endl;}
private:int _b = 1;
};void func()
{person b1;printf("vftptr:%p\n", *(int*) & b1);int i = 0;int* p1 = &i;int* p2 = new int;const char* p3 = "sad";printf("栈变量:%p\n", p1);printf("堆变量:%p\n", p2);printf("代码段常量:%p\n", p3);printf("代码段函数地址:%p\n", &base::func1);}int main()
{student s;person p;buy(s);buy(p);int size = sizeof(s);cout << size << endl;func();return 0;
}
问题:虚函数存在哪?虚函数表存在哪?
答:虚函数和普通函数都存在代码段、虚函数表也存在代码段

普通的函数、函数名就是地址(首地址)
成员函数的地址要加取地址符号&,以及要指定属于哪个类,也就是这样 &类名::函数名
虚表地址
class Base
{
public:virtual void fuc1(){cout << "fuc1" << endl;}virtual void fuc2(){cout << "fuc2" << endl;}
private:int a;
};class derive : public Base
{
public:virtual void fuc1(){ cout << "fuc1111" << endl; }virtual void fuc3(){cout << "fuc3" << endl;}
};typedef void(*VF_PTR)();//函数指针类型怎么写的
void PrintVFTable(VF_PTR* pTable)
{for(size_t i = 0; pTable[i] != 0; ++i){printf("vfTable[%d]:%p->", i, pTable[i]);VF_PTR f = pTable[i];f();//运行函数}cout << endl;
}int main()
{//student s;//person p;//buy(s);//buy(p);//int size = sizeof(s);//cout << size << endl;//func();derive a;Base b;PrintVFTable((VF_PTR*)(*(int*)&b));PrintVFTable((VF_PTR*)(*(int*)&a));return 0;
}
父类上面两行、子类为下面三行;
子类fuc1重写过了虚表地址就变了,没写fuc2但是继承了fuc2的虚表地址;

强转两次,(int*)是要取前4个字符,(VF_PTR*)强转函数指针

函数指针怎么写 void(*)()
type void(*a)(),这个a就代表函数指针了
多继承的子类的大小怎么计算?
继承几个父类就含有几个指针;
class Base1
{
public:virtual void fuc1() { cout << "b1:fuc1" << endl; }virtual void fuc2() { cout << "b1:fuc2" << endl; }
private:int a1;
};class Base2
{
public:virtual void fuc1() { cout << "b2:fuc1" << endl; }virtual void fuc2() { cout << "b2:fuc2" << endl; }
private:int a2;
};class derive2 : public Base1, public Base2
{virtual void fuc1() { cout << "b2:fuc1" << endl; }virtual void fuc3() { cout << "b2:fuc2" << endl; }private:int a3;
};int main()
{//student s;//person p;//buy(s);//buy(p);//int size = sizeof(s);//cout << size << endl;//func();//derive a;//Base b;//PrintVFTable((VF_PTR*)(*(int*)&b));//PrintVFTable((VF_PTR*)(*(int*)&a));cout << sizeof(derive2) << endl;derive2 a1;PrintVFTable((VF_PTR*)(*(int*)&a1));PrintVFTable((VF_PTR*)(*(int*)((char*)&a1 + sizeof(Base1))));return 0;
}

继承两个父类,两个指针的大小;
不同父类的虚表继承后不会共用;
derive2成员函数fuc3的虚表和Base1的虚表共用了,随机共用一个父类的虚表;
练习题
1、

2、
类中就只有变量、按顺序往下排;
p3是指向整块区域,所以首地址也是b1存的首地址;
p1也是b1存的首地址;
p2是b2的首地址;
所以选c;

虚函数和虚继承

是两个完全不同的概念;
用的都是virtual;
虚继承

菱形继承时,B、C继承A,D继承BC;

如上图使用虚继承,就会把公共的变量_a,放到一个地址上;
如果不用虚继承的话,就会有三个_a的地址;造成数据的冗余性;
二义性也是不用虚继承造成的,就是再回去找_a时,有很多_a;
相关文章:
多态--下
文章目录 概念多态如何实现的指向谁调谁?例子分析 含有虚函数类的大小是多少?虚函数地址虚表地址多继承的子类的大小怎么计算?练习题虚函数和虚继承 概念 优先使用组合、而不是继承; 继承会破坏父类的封装、因为子类也可以调用到父类的函数;…...
备考ICA----Istio实验16---HTTP流量授权
备考ICA----Istio实验16—HTTP流量授权 1. 环境准备 kubectl apply -f istio/samples/bookinfo/platform/kube/bookinfo.yaml kubectl apply -f istio/samples/bookinfo/networking/bookinfo-gateway.yaml访问测试 curl -I http://192.168.126.220/productpage2. 开启mtls …...
STM32-02基于HAL库(CubeMX+MDK+Proteus)GPIO输出案例(LED流水灯)
文章目录 一、功能需求分析二、Proteus绘制电路原理图三、STMCubeMX 配置引脚及模式,生成代码四、MDK打开生成项目,编写HAL库的GPIO输出代码五、运行仿真程序,调试代码 一、功能需求分析 在完成开发环境搭建之后,开始使用STM32GP…...
华为审核被拒提示: 您的应用存在(最近任务列表隐藏风险活动)的行为,不符合华为应用市场审核标准
应用审核意见: 您的应用存在(最近任务列表隐藏风险活动)的行为,不符合华为应用市场审核标准。 修改建议:请参考测试结果进行修改。 请参考《审核指南》第2.19相关审核要求:https://developer.huawei.com/c…...
数论与线性代数——整除分块【数论分块】的【运用】【思考】【讲解】【证明(作者自己证的QWQ)】
文章目录 整除分块的思考与运用整除分块的时间复杂度证明 & 分块数量整除分块的公式 & 公式证明公式证明 代码code↓ 整除分块的思考与运用 整除分块是为了解决一个整数求和问题 题目的问题为: ∑ i 1 n ⌊ n i ⌋ \sum_{i1}^{n} \left \lfloor \frac{n}{…...
Linux系统下安装jdk与tomcat【linux】
一、yum介绍 linux下的jdk安装以及环境配置,有两种常用方法: 1.使用yum一键安装。 2.手动安装,在Oracle官网下载好需要的jdk版本,上传解压并配置环境。 这里介绍第一种方法,在此之前简单了解下yum。 yum 介绍 yum&…...
matlab实现决策树可视化——信息增益、C4.5、基尼指数
代码:https://download.csdn.net/download/boyas/89074326...
如何使用Python进行网络编程和套接字通信?
如何使用Python进行网络编程和套接字通信? Python作为一种通用编程语言,具有强大的网络编程能力。它提供了丰富的库和工具,使得开发者可以轻松地实现网络编程和套接字通信。下面将详细介绍如何使用Python进行网络编程和套接字通信。 一、网…...
nodeJs 实现视频的转换(超详细教程)
前段时间拿到一个视频是4k的,没法播放,于是通过 node.js 和 ffmpeg 实现了视频的转换。在win10 系统下实现。 所需工具 node 16.19 直接安装 ffmpeg-5.1.1-essentials_build 解压后重名 ffmpeg 放到C盘 然后配置下环境变量 Git-2.42.0.2-64-bit 直接…...
Transformer - model architecture
Transformer - model architecture flyfish Transformer总体架构可分为四个部分: 输⼊部分 输出部分 编码器部分 解码器部分 输入部分 输出部分 输⼊部分包含: 源嵌⼊层和位置编码 ⽬标嵌⼊层和位置编码 输出部分包含: 线性层 softmax处理器 左侧编码器部分和右侧解码器部…...
Zookeeper学习一
初识 Zookeeper Zookeeper 是 Apache Hadoop 项目下的一个子项目,是一个树形目录服务(B树)。 Zookeeper 翻译过来就是 动物园管理员,他是用来管 Hadoop(大象)、Hive(蜜蜂)、Pig(小 猪)的管理员。简称zk …...
SAR教程系列7——在cadence中用Spectrum工具FFT仿真ADC的ENOB、SNR等动态性能指标
首先在仿真之前,你得有一个ADC。然后是思考如何仿真的问题,如何加激励,如何使用相关工具查看仿真结果。假定你有一个可以仿真的ADC,大致经过下列步骤可以得到ADC的相关动态性能指标。 第一步:在ADC后面接一个理想的DA…...
攻防世界:mfw[WriteUP]
根据题目提示考虑是git库泄露 这里在地址栏后加.git也可以验证是git库泄露 使用GitHack工具对git库进行恢复重建 在templates目录下存在flag.php文件,但里面并没有flag 有内容的只有主目录下的index.php index.php源码: <?phpif (isset($_GET[page…...
mysq性能优化-my.cnf配置文件参数调整
MySQL 优化配置文件(my.cnf 或 my.ini)是调整 MySQL 服务器性能的重要手段之一。以下是一些常见的场景,可以通过调整配置文件参数值来优化 MySQL: 1. **提高并发处理能力**: - innodb_buffer_pool_size:增…...
ddres( ) 组站星双差方程和设计矩阵
1 ddres( )参数介绍 rtklib中进行的单频解算 双差观测值,单差的模糊度 单频点双差 DD (double-differenced) phase/code residuals ------------------------------ x 模糊度 P 方差-协方差阵 sat 共识卫星列表 ns 共识卫星数量 y…...
【OpenCV】图像像素的遍历
1 前言 介绍两种遍历像素的方法(非指针、指针)。注意:.at() .ptr()的作用、用法。相关API: Mat对象.ptr() Mat对象.at() 2 代码及内容 #include "iostream" #include "opencv2/opencv.hpp"using namespac…...
(超简单)构建高可用网络应用:使用Nginx进行负载均衡与健康检查
当构建高可用的网络应用时,负载均衡是至关重要的技术之一。Nginx 是一个强大的开源反向代理服务器,提供了丰富的负载均衡功能,包括负载均衡算法和健康检查。在本篇博客中,我们将讨论如何使用 Nginx 进行负载均衡,并结合…...
华为OD面试手撕算法-合并排序数组
题目描述 本题是leetcode一道简单题:合并两个有序数组,但是对于时间和空间复杂度面试官明确给出了限制。 // 给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B。 编写一个方法,将 B 合并入 A 并排序。 // 初始化…...
云智慧发布对象关系型数据库CloudPanguDB,打破传统技术壁垒
近日,云智慧推出关系型数据库CloudPanguDB(中文名称:盘古数据库),旨在通过高兼容性能和创新技术架构,降低企业项目整体运营成本。 无论是处理海量复杂数据,还是构建清晰有序的数据结构关系&…...
6.8物联网RK3399项目开发实录-驱动开发之RTC实时时钟的使用(wulianjishu666)
90款行业常用传感器单片机程序及资料【stm32,stc89c52,arduino适用】 链接:https://pan.baidu.com/s/1M3u8lcznKuXfN8NRoLYtTA?pwdc53f RTC 使用 简介 AIO-3399J 开发板上有 一个集成于 RK808 上的RTC(Real Time Clock),主要功能有时钟,…...
【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
