图解多态原理

2023-11-05

●虚函数表:

class Base
{
public:
    virtual void Func1()
     {
        cout << "Func1()" << endl;
     }
private:
    int _b = 1;
};
void test()
{
    Base b;
    cout<<sizeof(b)<<endl;//8
}

通过测试发现b对象是8bytes除了_b成员,还多一个__vfptr放在对象的前面(注意有些平台可能会放到对象的最后面,这个跟平台有关)对象中的这个指针我们叫做虚函数表指针。

一个含有虚函数的类中都至少都有一个虚函数表指针,因为虚函数的地址要被放到虚函数表中, 虚函数表也简称虚表。

派生类的虚函数表:

class Base
{
public:
	virtual void Func1()
	{
		cout << "Base::Func1()" << endl;
	}
	virtual void Func2()
	{
		cout << "Base::Func2()" << endl;
	}
	void Func3()
	{
		cout << "Base::Func3()" << endl;
	}
private:
	int _b = 1;
};
class Derive :public Base
{
public:
	virtual void Func1()//重写
	{
		cout << "Derive::Func1()" << endl;
	}
private:
	int _d = 2;
};

int main()
{
	Base b;
	Derive d;
	return 0;
}

通过观察可以发现:

1. 派生类对象d中也有一个虚表指针,d对象由两部分构成,一部分是父类继承下来的成员,虚表指针也就是在这里。

2. 基类b对象和派生类d对象虚表是不一样的,这里我们发现Func1完成了重写,所以d的虚表中存的是重写的Derive::Func1

所以虚函数的重写也叫作覆盖,覆盖就是指虚表中虚函数的覆盖。重写是语法的叫法,覆盖是原理层的叫法。

区分重载,重写,重定义,隐藏,覆盖:

1>重载:在同一作用域且函数名和参数都相同的函数称为重载。

2>重写(覆盖):在基类和派生类的两个作用域中,函数名/返回值/参数都相同的虚函数。(协变除外,协变返回基类和派生                             类的指针或者引用)

3>重定义(隐藏):在基类和派生类的两个作用域中,函数名相同,不构成重写就是重定义。

3. Func2继承下来后是虚函数,所以放进了虚表,Func3也继承下来了,但是不是虚函数,所以不会 放进虚表。

4. 虚函数表本质是一个存虚函数指针的指针数组这个数组最后面放了一个nullptr

5.派生类的虚表生成:

      a>先将基类中的虚表内容拷贝一份到派生类虚表中

      b>如果派生类重写了基 类中某个虚函数,用派生类自己的虚函数覆盖虚表中基类的虚函数

      c>派生类自己新增加的虚函数按其在 派生类中的声明次序增加到派生类虚表的最后。

虚函数存在哪的?虚表存在哪的?

答:虚函数和普通函数一样的,都是存在代码段的,只是他的指针又存到了虚表中。

       虚表是存在常量区的,存的是虚函数指针。对象中存的不是虚表,存的是虚表指针。

多态的原理:

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

我们要达到多态,有两个条件,一个是虚函数覆盖,一个是对象的指针或引用调用虚函数。 为什么?

 

通过汇编来看多态的原理:

 

动态绑定与静态绑定

1. 静态绑定又称为前期绑定(早绑定)在程序编译期间确定了程序的行为也称为静态多态,比如:函数重载,构造函数调用。

2. 动态绑定又称后期绑定(晚绑定),是在程序运行期间,根据具体拿到的类型确定程序的具体行为,调用具体的函数,也称为动态多态。例如上面多态原理的分析。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

图解多态原理 的相关文章

  • 自动从 C# 代码进行调试过程并读取寄存器值

    我正在寻找一种方法来读取某个地址的 edx 注册表 就像这个问题中所问的那样 读取eax寄存器 https stackoverflow com questions 16490906 read eax register 虽然我的解决方案需要用
  • C++ 求二维数组每一行的最大值

    我已经设法用这个找到我的二维数组的每一行的最小值 void findLowest int A Cm int n int m int min A 0 0 for int i 0 i lt n i for int j 0 j lt m j if
  • 为什么 POSIX 允许在只读模式下超出现有文件结尾 (fseek) 进行搜索

    为什么寻找文件结尾很有用 为什么 POSIX 让我们像示例中那样在以只读方式打开的文件中进行查找 c http en cppreference com w c io fseek http en cppreference com w c io
  • 跨多个控件共享事件处理程序

    在我用 C 编写的 Windows 窗体应用程序中 我有一堆按钮 当用户的鼠标悬停在按钮上时 我希望按钮的边框发生变化 目前我有以下多个实例 每个按钮一个副本 private void btnStopServer MouseEnter ob
  • 如何针对 Nancy 中的 Active Directory 进行身份验证?

    这是一篇过时的文章 但是http msdn microsoft com en us library ff650308 aspx paght000026 step3 http msdn microsoft com en us library
  • C# 用数组封送结构体

    假设我有一个类似于 public struct MyStruct public float a 我想用一些自定义数组大小实例化一个这样的结构 在本例中假设为 2 然后我将其封送到字节数组中 MyStruct s new MyStruct s
  • HttpClient 像浏览器一样请求

    当我通过 HttpClient 类调用网站 www livescore com 时 我总是收到错误 500 可能服务器阻止了来自 HttpClient 的请求 1 还有其他方法可以从网页获取html吗 2 如何设置标题来获取html内容 当
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • 线程、进程和 Application.Exit()

    我的应用程序由主消息循环 GUI 和线程 Task Factory 组成 在线程中我调用一些第三方应用程序var p new Process 但是当我调用Application Exit 在消息循环中 我可以看到在线程中启动的进程仍在内存中
  • 我的 strlcpy 版本

    海湾合作委员会 4 4 4 c89 我的程序做了很多字符串处理 我不想使用 strncpy 因为它不会终止 我不能使用 strlcpy 因为它不可移植 只是几个问题 我怎样才能让我的函数正常运行 以确保它完全安全稳定 单元测试 这对于生产来
  • Windows 10 中 Qt 桌面应用程序的缩放不当

    我正在为 Windows 10 编写一个简单的 Qt Widgets Gui 应用程序 我使用的是 Qt 5 6 0 beta 版本 我遇到的问题是它根本无法缩放到我的 Surfacebook 的屏幕上 这有点难以判断 因为 SO 缩放了图
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • 检查 url 是否指向文件或页面

    我们需要以下内容 如果文件确实是文件 则从 URL 下载该文件 否则 如果它是一个页面 则什么也不做 举个简单的例子 我有以下命令来下载文件 My Computer Network DownloadFile http www wired c
  • char指针或char变量的默认值是什么[重复]

    这个问题在这里已经有答案了 下面是我尝试打印 char 变量和指针的默认值 值的代码 但无法在控制台上看到它 它是否有默认值或只是无法读取 ASCII 范围 include
  • 如何构建印度尼西亚电话号码正则表达式

    这些是一些印度尼西亚的电话号码 08xxxxxxxxx 至少包含 11 个字符长度 08xxxxxxxxxxx 始终以 08 开头 我发现这个很有用 Regex regex new Regex 08 0 9 0 9 0 9 0 9 0 9
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • GDK3/GTK3窗口更新的精确定时

    我有一个使用 GTK 用 C 语言编写的应用程序 尽管该语言对于这个问题可能并不重要 这个应用程序有全屏gtk window与单个gtk drawing area 对于绘图区域 我已经通过注册了一个刻度回调gtk widget add ti
  • 如何连接字符串和常量字符?

    我需要将 hello world 放入c中 我怎样才能做到这一点 string a hello const char b world const char C string a hello const char b world a b co
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但

随机推荐

  • GraphEdit使用

    GraphEdit 是一个用于建立和测试Filter graph 的可视化工具 在DirectX SDK 中附带一个可执行程序版本 在SDK目录中的Bin DXUtils graphedt exe 你可以快速测试你建立的Filter gra
  • 因果论(五)——Structural Causal Model(SCM 结构因果模型、函数模型和图模型)

    一 核心思想 SCM的核心思想是因果图 因果图之前已经介绍过 SCM和RCM是等价的 SCM的关键在于图模型 来源于贝叶斯网络 将Bayes网络加上外部干预 用来定义外部干预的因果作用和描述多个变量之间的因果关系 利用因果网络不仅能定量评价
  • 自动化测试框架实战详解

    B站最通俗易懂 Python接口自动化测试从入门到精通 超详细的进阶教程 看完这套视频就够了 前言 之前文章跟大家分享了一下自己在接口自动化测试中进行测试准备的一些相关知识点 接下来本篇文章详细分享一下接口自动化框架设计的思路总结 希望能对
  • 使用POI同时对Excel文件进行读和写操作时避免Invalid header signatu

    这学期学到了数据库概论 课程设计需要做一个DBMS 图方便想把数据什么的存到xls文件中 在使用poi对excel文件同时进行读和写操作时 如果这样写 public void test try File file new File user
  • linux sed命令,如何替换换行符“\n”

    linux sed命令如何替换换行符n 实现方法 第一种方法使用test跳转命令实现替换换行符 branch和test区别 第二种方法使用branch跳转命令实现替换换行符 linux sed命令 如何替换换行符 n 在一次sed使用中 执
  • 关于GD32E230进入睡眠后无法烧录程序解决方法

    软件安装 1 到GD32官网兆易创新 gd32mcu com 找到下图文件下载并安装 2 安装软件 傻瓜式安装 就不多讲了 直接一步到底 3 进入主题 打开刚刚下载好的软件 开发板设置 1 连接开发板上的串口 2 进入BOOT0模式 接3
  • linxu下c/c++遍历文件夹获取文件

    最近工作需要 需要遍历文件夹下的文件 但是我发现遇到两个非常有意思的问题 记录一下 测试的平台为 PC linux Tina linux Linux version 5 15 0 41 generic buildd lcy02 amd64
  • JDK JRE JVM之间的关系

    文章目录 1 从定义的角度解释JDK JRE JVM 2 详细介绍JDK 3 详细介绍JRE 4 详细介绍JVM 1 JVM内部区域划分 5 如何运行一个java程序 本篇文章仅仅是个人片面观点 可能有错误或者表述不清的地方 1 从定义的角
  • Flink从入门到放弃(九)-万字讲解CDC设计(1)

    一 准备工作 在开始研究Flink CDC原理之前 本篇先以CDC1 0版本介绍 后续会延伸介绍2 0的功能 需要做以下几个工作 本篇以Flink1 12环境开始着手 打开Flink官网 查看Connector模块介绍 打开Github 下
  • Unicode与JavaScript详解

    上个月 我做了一次分享 详细介绍了Unicode字符集 以及JavaScript语言对它的支持 下面就是这次分享的讲稿 一 Unicode是什么 Unicode源于一个很简单的想法 将全世界所有的字符包含在一个集合里 计算机只要支持这一个字
  • 水箱建模最小二乘法_Comsol Multiphysics for Mac(建模仿真软件)

    COMSOL Multiphysics 是一款全球通用的基于高级数值方法和模拟物理场问题的通用软件 拥有 网格划分 研究和优化 求解器 可视化和后处理 仿真 App等相关功能 轻松实现各个环节的流畅进行 它能够解释耦合或多物理现象 附加产品
  • oracle 19c rac asm磁盘绑定的方法

    multipath 通过scsi id udev 通过scsi id oracle AFD 直接绑定后在 dev oracleafd disks 下面生成设备文件 asmcmd afd label OCR1 dev sda init 虚拟机
  • 【华为OD机试真题 JAVA】数组二叉树

    JS版 华为OD机试真题 JS 数组二叉树 标题 数组二叉树 时间限制 1秒 内存限制 262144K 语言限制 不限 二叉树也可以用数组来存储 给定一个数组 树的根节点的值存储在下标1 对于存储在下标N的节点 它的左子节点和右子节点分别存
  • QT-自定义消息提示框,好看大气

    QT 自定义消息提示框 好看大气 前言 一 演示效果 二 关键程序 三 下载链接 前言 原生的QT提示框总是让人觉得难以接受 因此特定重新封装一个类来替换原生的 使用过程跟原生的一致 使用比较方便 一 演示效果 二 关键程序 include
  • PHP常见加密函数(总结)

    1 加密算法汇总 比较常用的算法 md5 加密 crypt 加密 sha1加密 URL编码加密 base64编码加密 信息加密技术分为三类 单项散列加密 对称散列加密 非对称散列加密 1 1单项散列加密 MD5加密 crypt 加密 sha
  • 数据结构——深度优先遍历(DFS)无向连通图

    以下是数据结构中关于深度优先遍历无向连通图的操作 编程风格参考严蔚敏版数据结构 其实深度优先遍历就是二叉树的先序遍历的推广 头文件以及宏定义 include
  • css渐变

    1 线性渐变 是从一个方向到另一个方向的渐变 属性值 background linear gradient 颜色 默认值 从上到下线性渐变 代码 结果 属性延伸 1 改变渐变方向 从下到上 background linear gradien
  • RecyclerView 网格布局是设置分割线

    1 分割线 public class DividerGridItemDecoration extends RecyclerView ItemDecoration private static final int ATTRS new int
  • 在用apt install中如何选择安装路径?

    apt install并不会选择软件包的安装路径 这个路径是在软件包里面记录好路径的相关信息的 一个deb包 只是一堆文件 文件夹的压缩包而已 而这个包里面记录了这些文件 文件夹应该安装的位置 因此 简单点说 你不能够在apt instal
  • 图解多态原理

    虚函数表 class Base public virtual void Func1 cout lt lt Func1 lt lt endl private int b 1 void test Base b cout lt