多态是面向对象编程三大特性之一,通过多态我们可以大大增强代码的复用性,也会使代码整体更紧凑简洁;
多态可以分为静态多态动态多态两类,

静态多态就比如函数重载或者运算符重载;
动态多态则是派生类虚函数实现的运行时的多态;(地址软绑定

它们就是因为在函数地址绑定时机不同所以有所区分
动态:运行时确定函数地址;
静态:编译时确定函数地址;

实现多态需要满足两个条件:
1、有继承关系
2、子类重写父类中的虚函数(重写:函数返回值类型 函数名 参数列表 完全一致称为重写)
有了这些,我们就可以使用多态了,使用多态同样需要满足一个条件:
⚠️父类指针或引用指向子类对象

举个例子:
先定义一个父类对象,

class Father {public:virtual void eyes() {cout << "双眼皮" << endl;}
};

virtual声明的函数会变成一个虚函数,这个就是父类中的虚函数,接下来我们声明两个子类,

class Son1 : public Father {public:void eyes() {cout<< "单眼皮" << endl;}
};
class Son2 : public Father {public:void eyes() {cout<< "单双眼皮" << endl;}
};

这里我们声明了两个子类对象,都以公共继承的方式继承了父类的对象,并且都重写了父类中的eyes()函数,这时我们写一个测试函数并在主函数中调用,

void text(Father &v) {v.eyes();
}
int main () {Son1 s1;text(s1);// Father &v = s1Son2 s2;text(s2);// Father &v = s2return 0;
}

输出结果会是:

单眼皮
单双眼皮

在调用过程中父类的引用指向了子类的对象,因为父类的eyes是虚函数且子类重写了该函数,所以该引用就会走子类的eyes,这就是多态的实现;
那么多态的底层原理又是什么呢?
还是刚才的父类,如果我们不加virtual,并计算一下这个父类对象到底占多少空间,我们重写一下代码

class Father {public:void eyes() {cout << "双眼皮" << endl;}
};void text01() {cout << "sizeof Father = " << sizeof(Father) <<endl;}

如果我们在主函数调用text01,输出为:sizeof Father = 1,即此时的Father只占用一个字节的空间(成员函数eyes不属于类的对象,它们分开存储,所以相当于一个空类占用了1一个字节),
那么加上virtual后呢,当我们加上virtual后再运行就会发现输出变成了:
sizeof Father = 4,这就说明了加上virtual后该类的内容就发生了改变,什么东西占四个字节?整形?单精度浮点型?都不大可能,当然还有一个东西占四个字节,那就是指针,指针始终占四个字节;这里就是一个指针,但是这又是什么类型的指针呢?
⚠️这个指针叫做 :vfptr

v:virtual
f:function
ptr: pointer

直译过来就是:虚函数(表)指针
回到代码,此时的Father类的内部就会生成一个vfptr,它会指向一个虚函数表,即⚠️vftable,
那么vftable又是什么?
vftable内部会记录虚函数的地址,在这个Fathe类中,虚函数表中记录的地址就是:
&Father :: eyes() 意思就是Fathe作用域下的函数eyes()的地址;

⚠️那么子类Son1继承后又是怎样的呢?
如果Son1只单纯的继承Father,并不重写eyes函数,那么它就会把父类中的所有东西继承过来,包括父类中的vfptr和vftable,这时继承过来的的vftable内部依然是
&Father :: eyes()
但是若子类Son1重写了eyes函数,这时子类就会把虚函数表中的内容进行一个覆盖操作,此时的子类中的虚函数表内部会替换为子类的虚函数地址,即在这里子类内部就会发生:
&Father :: eyes() 变成 &Son1 :: eyes() ,即 &Father :: eyes() 就被 &Son1 :: eyes() 给覆盖了,这时子类Son1的虚函数表中就只有 &Son1 :: eyes() 了(Son1的eyes函数地址);
但是父类Father中的虚函数表并没有被覆盖,依然是 &Father :: eyes()

⚠️在发生多态时,当父类的指针或者引用指向子类对象时,例如:

Son1 s1;
Father &father = s1;

当father调用eyes()函数的时候,因为此时的虚函数指针指向的是一个Son1对象,它就会去Son1的虚函数表中找这个eyes函数,这就是在运行阶段发生了动态多态。

多态及其内部原理剖析相关推荐

  1. git gui fetch不到文件_Git内部原理剖析,有比这还详细的吗?

    1.1. 为什么写这篇文章 写这篇文章的本意有二: 工作安排原因,常有同事询问我一些关于 Git 的问题,总觉得自己解释的不够透彻,因此觉得有必要深入了解一下. 目前中文的 Git 教程往往本末倒置, ...

  2. C++_类和对象_C++多态_多态的原理剖析---C++语言工作笔记070

    然后我们再去看c++中,多态实现的原理. 前面我们说,多态有,静态多态和动态多态,然后并且使用了一下多态,做了个案例. 并且我们说,多态的实现需要满足条件,就是首先要有继承关系,要有父类,子类, 然后 ...

  3. 猿创征文|深入剖析多态的实现原理与虚函数指针

    学习导航 一.多态实现原理 二.不同情况下的虚函数表 (1)单继承无虚函数覆盖 (2)单继承有虚函数覆盖 (3)多继承无虚函数覆盖 (4)多继承有虚函数覆盖 三.对虚函数指针与虚函数表的深入理解 (1 ...

  4. 虚函数:多态的实现原理

    一.序言  C++ 中的虚函数的作用主要是实现了多态的机制.关于多态,说白了就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数(当然引用也可以达到该目的,引用也是指针的另一 ...

  5. fastText的原理剖析

    fastText的原理剖析 1. fastText的模型架构 fastText的架构非常简单,有三层:输入层.隐含层.输出层(Hierarchical Softmax) 输入层:是对文档embeddi ...

  6. 彻底搞透视觉三维重建:原理剖析、代码讲解、及优化改进

    视觉三维重建 = 定位定姿 + 稠密重建 + surface reconstruction +纹理贴图.三维重建技术是计算机视觉的重要技术之一,基于视觉的三维重建技术通过深度数据获取.预处理.点云配准 ...

  7. Elasticsearch分布式一致性原理剖析(一)-节点篇

    2019独角兽企业重金招聘Python工程师标准>>> 摘要: ES目前是最流行的开源分布式搜索引擎系统,其使用Lucene作为单机存储引擎并提供强大的搜索查询能力.学习其搜索原理, ...

  8. 统计学习方法|支持向量机(SVM)原理剖析及实现

    欢迎直接到我的博客查看最近文章:www.pkudodo.com.更新会比较快,评论回复我也能比较快看见,排版也会更好一点. 原始blog链接: http://www.pkudodo.com/2018/ ...

  9. 统计学习方法|逻辑斯蒂原理剖析及实现

    欢迎直接到我的博客查看最近文章:www.pkudodo.com.更新会比较快,评论回复我也能比较快看见,排版也会更好一点. 原始blog链接: http://www.pkudodo.com/2018/ ...

最新文章

  1. 2018-3-18Zookeep
  2. Rancher 推出 k3OS,业界首个 Kubernetes 操作系统
  3. 玩转Regsvr32命令
  4. java 调用远程服务_java调用(请求)远程服务地址
  5. VTK:可视化之AnnotatedCubeActor
  6. leetcode 1339. Maximum Product of Splitted Binary Tree | 1339. 分裂二叉树的最大乘积(树形dp)
  7. mysql 5.6加用户_Mysql 5.6添加修改用户名和密码的方法
  8. es6 Promise.done(),Promise.finally()
  9. 重温WCF之数据契约和序列化(四)
  10. python123电脑登录不了_python(14)- 简单练习:登录账户失败三次,账户自动锁定...
  11. Thrift搭建分布式微服务(四)
  12. windows搭建yolo环境
  13. vmware挂载共享目录
  14. Mysql常用内置函数
  15. ElasticSearch 7.15.2 使用java canal 接入实现灵活化增量数据准实时同步
  16. Wireless Power Tranmissions
  17. java手机验证码代码_发送手机验证码
  18. instanceof有什么作用
  19. 大学物理·第11章【光学】
  20. Java中如何实现QR(二维码)的生成

热门文章

  1. pdo mysql fetchall_pdo fetch,pdo fetchAll,pdo query,pdo prepare用法举例
  2. win7 nvme 支持补丁_UpdatePack7R2 v20.8.13 Win7 更新补丁包
  3. java 反射模式_java 设计模式——反射机制的应用
  4. 运维工程师仪表免费换新活动开始了…任何品牌万用表、钳表、测温仪都可以换福禄克万用表、钳表、测温仪...
  5. python输入两个变量的值、输出大的_Python 变量和输入输出 关卡二
  6. python能print中文吗_win10中文版,python的print不能打印中文字符?
  7. 成功解决MSB8020 The build tools for v141 (Platform Toolset = ‘v141‘) cannot be found. To build using the
  8. 成功解决基于VS2015(Visual Studio2015)编写C++程序调试时弹出窗口一闪而过的问题
  9. 成功解决ImportError: [joblib] Attempting to do parallel computing without protecting your import on a sy
  10. Py之MT:Multithreaded的简介、引入、使用方法之详细攻略