多态--下

文章目录

      • 概念
      • 多态如何实现的指向谁调谁?
        • 例子
        • 分析
      • 含有虚函数类的大小是多少?
      • 虚函数地址
      • 虚表地址
      • 多继承的子类的大小怎么计算?
      • 练习题
      • 虚函数和虚继承

概念

优先使用组合、而不是继承;
继承会破坏父类的封装、因为子类也可以调用到父类的函数;
子类必须实现父类的纯虚函数;
内联函数没有地址,他是直接在定义的地方展开。所以不能是虚函数、虚函数是要有地址的;
虚函数不能是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出来换一个地址,把新的内容覆盖了;
image.png
2、调用时传过去的参数累心是谁的就指向谁的虚函数表,s是student类型那就是用student里面的函数;
image.png
2、子类虚函数不重写会怎样
如果不重写,那父级和子级虚函数表的地址是相同的
image.png

含有虚函数类的大小是多少?

普通函数不占空间,虚函数有个指针、所以站指针的大小空间,32位的4字节、64位的8字节;
在类里面:虚函数占一个指针的大小,不管有多少个虚函数就只占一个指针的大小;对象里面只是存了一个指针指向这个虚表
虚表的大小才要看有几个虚函数;
多继承的子类,继承了几个父类就有几个父类的指针大小
如下就一个虚函数64位
image.png
计算方法和结构体其实一样,内存对齐
加了一个int变量,理应8+4 = 12,但是最小对齐数为8,类的大小是其成员最小对齐数的整数倍;所以是16;
image.png

虚函数地址

#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;
}

问题:虚函数存在哪?虚函数表存在哪?
答:虚函数和普通函数都存在代码段、虚函数表也存在代码段
image.png
普通的函数、函数名就是地址(首地址)
成员函数的地址要加取地址符号&,以及要指定属于哪个类,也就是这样 &类名::函数名

虚表地址

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的虚表地址;
image.png
强转两次,(int*)是要取前4个字符,(VF_PTR*)强转函数指针
image.png
函数指针怎么写 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;
}

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

练习题

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

虚函数和虚继承

image.png
是两个完全不同的概念;
用的都是virtual;

虚继承
image.png
菱形继承时,B、C继承A,D继承BC;

如上图使用虚继承,就会把公共的变量_a,放到一个地址上;
如果不用虚继承的话,就会有三个_a的地址;造成数据的冗余性;
二义性也是不用虚继承造成的,就是再回去找_a时,有很多_a;

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

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

相关文章

RESTful规范总结

概念&#xff1a;RESTful&#xff08;Representational State Transfer 的缩写&#xff09;是一种广泛使用的API架构风格。 1.资源&#xff1a;在REST API的设计中&#xff0c;首先需要面向资源建模&#xff0c;其中每个节点是是一个简单资源或集合资源。 1.1一个集合包含相同…

基于Uni-app的体育场馆预约系统的设计与实现

个人介绍 hello hello~ &#xff0c;这里是 code袁~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的…

如何操作RAID 0阵列的扩容?

正文共&#xff1a;1888 字 23 图&#xff0c;预估阅读时间&#xff1a;2 分钟 RAID&#xff08;Redundant Array of Independent Disks&#xff09;即独立磁盘冗余阵列&#xff0c;通常简称为磁盘阵列&#xff0c;在高级磁盘阵列中&#xff0c;部分物理存储空间会用来记录保存…

【性能调优】Java服务端性能优化与实战

一、背景 降本增效&#xff1a;随着公司业务的发展和用户规模的增加&#xff0c;当前服务的QPS已经远远不能满足业务需求&#xff0c;需要申请更多CPU资源&#xff0c;来提升QPS&#xff0c;满足业务发展&#xff0c;但是公司硬件资源有限&#xff0c;额外申请多余资源&#x…

OpenHarmony实战:小型系统器件驱动移植

本章节讲解如何移植各类器件驱动。 LCD驱动移植 移植LCD驱动的主要工作是编写一个驱动&#xff0c;在驱动中生成模型的实例&#xff0c;并完成注册。 这些LCD的驱动被放置在源码目录//drivers/hdf_core/framework/model/display/driver/panel中。 创建Panel驱动 创建HDF驱动…

vulnhub pWnOS v2.0通关

知识点总结&#xff1a; 1.通过模块来寻找漏洞 2.msf查找漏洞 3.通过网站源代码&#xff0c;查看模块信息 环境准备 攻击机&#xff1a;kali2023 靶机&#xff1a;pWnOS v2.0 安装地址&#xff1a;pWnOS: 2.0 (Pre-Release) ~ VulnHub 在安装网址中看到&#xff0c;该靶…

day10 java封装性

封装性 为什么有封装性&#xff1f; 为了保护数据不被随意修改&#xff0c;隐藏类的实现细节。增强了代码的安全性和可维护性。 该隐藏隐藏 该暴露暴露 封装性的实现&#xff1f; 让调用者只能通过方法操作属性。可以在方法中加入一些限制条件或数据检查的操作。 封装性的直…

计算机服务器中了helper勒索病毒怎么办,helper勒索病毒解密流程步骤

随着网络技术在企业中的不断应用&#xff0c;越来越多的企业离不开网络&#xff0c;网络为企业提供了极大便利&#xff0c;大大提升了生产运营效率&#xff0c;由此而产生的网络数据安全问题也成为了企业关心的主要话题。近期&#xff0c;云天数据恢复中心接到多家企业的求助&a…

jQuery(二)

文章目录 1.jQuery操作节点1.查找节点&#xff0c;修改属性1.基本介绍2.切换图片案例 2.创建节点1.基本介绍2.内部插入3.外部插入4.小结1.插入方法说明2.两种插入方法的区别 5.插入元素实例6.移动元素实例 3.删除节点1.基本介绍2.代码实例 4.复制节点1.基本介绍2.代码实例 5.替…

文心一言 VS 讯飞星火 VS chatgpt (227)-- 算法导论16.3 9题

九、证明&#xff1a;对于一个由随机生成的8位字符组成的文件&#xff0c;没有任何压缩方法可以望将其压缩、哪怕只是压缩一位。(提示&#xff1a;比较可能的文件数量和可能的编码文件数量。) 文心一言&#xff1a; 确实&#xff0c;对于一个由随机生成的8位字符组成的文件&a…

【动态】江西省小型水库安全监测能力提升试点项目通过验收

近日&#xff0c;由北京国信华源科技有限公司和长江勘测规划设计研究有限责任公司联合承建的江西省小型水库安全监测能力提升试点项目圆满通过验收。 在项目业主单位的组织下&#xff0c;省项目部、特邀专家、县水利局二级项目部以及项目设计、监理、承建等单位的代表组成验收工…

GLM论文研读

一、原文链接 论文&#xff1a;https://arxiv.org/pdf/2103.10360.pdf 二、原文翻译 摘要&#xff1a; 目前已经发展出多种预训练模型&#xff0c;包括自编码模型&#xff08;如BERT&#xff09;、自回归模型&#xff08;如GPT&#xff09;和编码器-解码器模型&#xff08;…

详细盘点Vue3项目中的各种组件文件夹(用于存放‘.vue’文件)

components 文件夹 存放通用的、可复用的组件&#xff1b; 通常用于构建页面中的具体功能模块。在项目中多次使用&#xff0c;并且不依赖于具体的业务逻辑。 比如&#xff1a;导航栏组件 navbar.vue layouts 文件夹 存放页面的整体布局组件 default.vue <script setup…

VMware创建Ubuntu虚拟机详细教程

下载ISO映像文件 进入官网下载&#xff1a;Download Ubuntu Desktop | Download | Ubuntu 下面是一些其他的下载路径&#xff1a; 中国官网 https://cn.ubuntu.com/ 中科大源 Index of /ubuntu-releases/ (ustc.edu.cn) 阿里云开源镜像站 ubuntu-releases安装包下载_开源镜像…

2024 ccfcsp认证打卡 2022 09 01 如此编码

2022 09 01 如此编码 题解1题解2 题解1 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt(); // 天数int m sc.nextInt(); // 科目数int[] b new int[n 1]; // 存放结果的数…

虚拟机与开发板之间互传文件、文件夹

1.配置桥接模式实现外网访问 1.1设置 VMnet0 要桥接的网卡 打开【编辑】-【虚拟网络编辑器】 选择【更改设置】 选择【VMnet0】&#xff0c;选择桥接到宿主机上的哪个网卡。 通过打开安装虚拟机的宿主机的【网络适配器】&#xff0c;可以查看网卡名称。 1.2虚拟机配置桥接模式…

基于springboot实现校园周边美食探索及分享平台系统项目【项目源码+论文说明】

基于springboot实现园周边美食探索及分享平台系统演示 摘要 美食一直是与人们日常生活息息相关的产业。传统的电话订餐或者到店消费已经不能适应市场发展的需求。随着网络的迅速崛起&#xff0c;互联网日益成为提供信息的最佳俱渠道和逐步走向传统的流通领域&#xff0c;传统的…

搭建好WordPress网站后的基本操作流程

考虑到很多朋友是第一次使用WordPress&#xff0c;这里给大家分享一下基本的WordPress操作流程&#xff0c;你可以跟着实际情况决定操作步骤。 1.设置网站SSL安全证书。 我采用的是Hostease家的Linux主机产品&#xff0c;自带免费SSL证书 。支持一键安装wordpress程序。 2.进…

《PDVC》论文笔记

PS&#xff1a;模型代码解释清明后出 原文链接&#xff1a; [2108.07781v1] End-to-End Dense Video Captioning with Parallel Decoding (arxiv.org) 原文笔记&#xff1a; What&#xff1a; End-to-End Dense Video Captioning with Parallel Decoding 并行解码的端到端…

蓝牙BLE开发——如何实时监听蓝牙适配器状态变化及回调

uniapp 监听蓝牙适配器状态变化事件 近年来开发项目中接触比较多的与硬件设备对接&#xff0c;通过蓝牙与设备通讯&#xff1b;开发 App、微信小程序&#xff0c;今天分享其中如何监听蓝牙适配&#xff1b;近期比较忙&#xff0c;不定时更新&#xff0c;有时间会分享 uniapp开发…