C++多态及其实现原理
1. 多态的定义:多态含义为一个事物有多种形态。在C ++程序设计中,多态性是指具有不同功能的函数可以用同一个函数名,这样就可以用一个函数名调用不同内容的函数,主要分为静态多态和动态多态;
静态多态:就是重载,因为在编译期决议确定,所以称为静态多态。在编译时就可以确定函数地址。
动态多态:就是通过继承重写基类的虚函数实现的多态,因为是在运行时确定决议,所以称为动态多态。运行时在虚函数表中寻找调用函数的地址。
2. 多态的现象:当子类中重写了父类的虚函数,那么通过父类的指针或者引用指向父类对象或着子类对象;用该父类指针或者引用调用父子中被重写的函数;就会有父类指针指向父类对象,调用的是父类中的虚函数;父类指针指向的是子类对象,调用的是子类虚函数;此时,也符合赋值兼容规则;不贵父类的指针或者引用指向父类对象或者子类对象;这个父类指针或者引用都只能访问父类的部分。
3. 动态多态原理:动态多态依靠运行时的类型检查来进行函数的迟绑定。声明一个类时,如果类中有虚方法,则自动在类中增加一个虚函数指针,该指针指向的是一个虚函数表,虚函数表中存着每个虚函数真正对应的函数地址。动态多态采用一种延迟绑定技术,普通的函数调用,在编译期间就已经确定了调用的函数的地址,所以无论怎样调用,总是那个函数,但是拥有虚函数的类,在调用虚函数时,首先去查虚函数表,然后再确定调用的是哪一个函数,所以,调用的函数是在运行时才会确定的。
· 当指向父类的对象时,由于本身是父类指针;且父类对象模型中的虚函数表指针所指向的虚函数表中只存放父类的虚函数地址;所以父类的指针调用的重写虚函数时父类的虚函数;
· 当父类指针指向子类对象时,此时子类对象中的(父类的虚函数表指针)所指的虚函数表中的(父类重写虚函数的地址)被改写为(子类的重写虚函数的地址),所以此时父类指针访问子类中父类的虚函数表时,找到的要调用的同名虚函数的地址就是子类的同名虚函数地址;所以父类指针调用就是子类的重写的同名虚函数;
虚函数重写(覆盖)的实质就是重写父类虚函数表中的父类虚函数地址;
4. 虚表指针初始化问题,当创建子类对象时,编译器的执行顺序:
· 对象在创建时,由编译器对 vptr 进行初始化
· 子类的构造会先调用父类的构造函数,这个时候 vptr 会先指向父类的虚函数表
· 子类构造的时候,vptr 会再指向子类的虚函数表(这也就是在父类或者子类的构造函数中调用虚成员函数不会实现多态的原因)
· 对象的创建完成后,vptr 最终的指向才确定
5. C++类继承中的构造函数和析构函数和多态的关系
a.构造函数不能实现多态:
子类的构造会先调用父类的构造函数,这个时候 vptr 会先指向父类的虚函数表;子类构造的时候,vptr 会再指向子类的虚函数表;
b. 析构函数可以实现多态:
在用基类指针指向派生类时,在基类析构函数声明为virtual的时候,delete基类指针,会先调用派生类的析构函数,再调用基类的析构函数;
c. 注意事项:在基类析构函数没有声明为virtual的时候,delete基类指针,只会调用基类的析构函数,而不会调用派生类的析构函数,这样会造成销毁对象的不完全;
C++多态及其实现原理的更多相关文章
- c++编译器对多态的实现原理总结
问题:定义一个空的类型,里面没有任何的成员变量或者成员函数,对这个类型进行 sizeof 运算,结果是? 结果是1,因为空类型的实例不包含任何信息,按道理 sizeof 计算之后结果是0,但是在声明任 ...
- Java 多态的实现原理
一个对象变量可以指示多种实际类型的现象称为多态 允许不同类的对象对同一消息做出响应.方法的重载.类的覆盖正体现了多态. 1.多态的机制 1.1 本质上多态分两种 .编译时多态(又称静态多态) .运行时 ...
- 多态原理探究-从C++编译器角度理解多态的实现原理
理论知识: 当类中声明虚函数时,编译器会在类中生成一个虚函数表. 虚函数表是一个存储类成员函数指针的数据结构. 虚函数表是由编译器自动生成与维护的. virtual成员函数会被编译器放入虚函数表中. ...
- c/c++ 多态的实现原理分析
多态的实现原理分析 当类里有一个函数被声明成虚函数后,创建这个类的对象的时候,就会自动加入一个__vfptr的指针, __vfptr维护虚函数列表.如果有三个虚函数,则__vfptr指向的是第一个虚函 ...
- 从虚拟机指令执行的角度分析JAVA中多态的实现原理
从虚拟机指令执行的角度分析JAVA中多态的实现原理 前几天突然被一个"家伙"问了几个问题,其中一个是:JAVA中的多态的实现原理是什么? 我一想,这肯定不是从语法的角度来阐释多态吧 ...
- Java技术——多态的实现原理
.方法表与方法调用 如有类定义 Person, Girl, Boy class Person { public String toString(){ return "I'm a person ...
- java多态的实现原理(JVM调用过程)(综合多篇文章,参考见文末)
一个对象变量可以指示多种实际类型的现象称为多态 允许不同类的对象对同一消息做出响应.方法的重载.类的覆盖正体现了多态. 1.多态的机制 1.1 本质上多态分两种 1.编译时多态(又称静态多态) 2.运 ...
- c++的动态绑定和静态绑定及多态的实现原理(摘)
C++多态的实现原理 为了支持c++的多态性,才用了动态绑定和静态绑定.理解它们的区别有助于更好的理解多态性,以及在编程的过程中避免犯错误. 需要理解四个名词:对象的静态类型:对象在声明时采用的类型. ...
- C++学习笔记-多态的实现原理
深入了解多态的实现原理,有助于提高对于多态的认识 多态基础 多态的实现效果 多态:同样的调用语句有多种不同的表现形态 多态实现的三个条件 有继承.有virtual重写.有父类指针(引用)指向子类对象 ...
- C++ 一篇搞懂多态的实现原理
虚函数和多态 01 虚函数 在类的定义中,前面有 virtual 关键字的成员函数称为虚函数: virtual 关键字只用在类定义里的函数声明中,写函数体时不用. class Base { virtu ...
随机推荐
- 3194. 【HNOI模拟题】化学(无标号无根树计数)
Problem 求\(n\)个点的每个点度数不超过\(4\)的无标号无根树个数. Data constraint \(1\le n\le 500\) Solution 尝试着把问题一般化.我们来考虑一 ...
- Python菜鸟快乐游戏编程_pygame(4)
Python菜鸟快乐游戏编程_pygame(博主录制,2K分辨率,超高清) https://study.163.com/course/courseMain.htm?courseId=100618802 ...
- 011 Socket定义客户端
引入命名空间: using System.Net; using System.Net.Sockets; using System.Threading;
- Vue学习笔记五:事件修饰符
目录 什么是事件修饰符 没有事件修饰符的问题 HTML 运行 使用事件修饰符 .stop阻止冒泡 .prevent 阻止默认事件 .capture 添加事件侦听器时使用事件捕获模式 .self 只当事 ...
- ACM-ICPC 2018 沈阳赛区网络预赛 B Call of Accepted(表达式求值)
https://nanti.jisuanke.com/t/31443 题意 给出一个表达式,求最小值和最大值. 表达式中的运算符只有'+'.'-'.'*'.'d',xdy 表示一个 y 面的骰子 ro ...
- window配置ftp服务,代码客户端上传下载文件
1 开启ftp服务 打开控制面板,点击程序,找到程序和功能,点击”打开或关闭windows功能” 找到“Internet信息服务”,点击前面的加号,展开功能,勾选”FTP服务”,“FTP扩展性”,“I ...
- localhost 将您重定向的次数过多
localhost 将您重定向的次数过多 问题描述:在项目中,出现 localhost 将您重定向的次数过多 ,有可能是因为设置重定向的时候,自己重定向到自己,或者重定向成环,导致无限的重定向.检查重 ...
- 第四周WordCount优化
一.GitHub地址 https://github.com/kawoyi/Advanced-WordCounter最终由组长整合的组长github 二.psp表格 三.个人模块及实现 我负责的是输入模 ...
- postgresql设置主键
replace(((uuid_generate_v4())::character varying)::text, '-'::text, ''::text)
- 在vscode中使用eslint+prettier格式化vue项目代码 (转载)
ESlint:javascript代码检测工具,可以配置每次保存时格式化js,但每次保存只格式化一点点,你得连续按住Ctrl+S好几次,才格式化好,自行体会~~ vetur:可以格式化html.标准c ...