C++虚函数原理
类中的成员函数分为静态成员函数和非静态成员函数,而非静态成员函数又分为普通函数和虚函数。
Q: 为什么使用虚函数
A: 使用虚函数,我们可以获得良好的可扩展性。在一个设计比较好的面向对象程序中,大多数函数都是与基类的接口进行通信。因为使用基类接口时,调用基类接口的程序不需要改变就可以适应新类。如果用户想添加新功能,他就可以从基类继承并添加相应的新功能。
Q: 简述C++虚函数作用及底层实现原理
A: 要点是要答出虚函数表和虚函数表指针的作用。
虚函数是用来实现动态绑定的。
C++中虚函数使用虚函数表和虚函数表指针实现,虚函数表是一个类的虚函数的地址表,用于索引类本身以及父类的虚函数的地址,假如子类重写了父类的虚函数,则对应在虚函数表中会把对应的虚函数替换为子类的函数的地址(子类中可以不是虚函数,但是必须同名);虚函数表指针存在于每个对象中(通常出于效率考虑,会放在对象的开始地址处),它指向对象所在类的虚函数表的地址;在多继承环境下,会存在多个虚函数表指针,分别指向对应不同基类的虚函数表。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
虚函数表是每个(有虚函数的)类对应一个。虚函数表指针是每个对象对应一个。
虚函数表里只能存放虚函数,不能存放普通函数。
如果一个函数不是虚函数,那么对它的调用(即该函数的地址)在编译阶段就会确定。调用虚函数的话(它的地址)要运行时才能确定。
虚函数的函数入口是动态绑定的。在运行时,程序根据基类指针指向的实际对象,来调用该对象对应版本的函数。(用该对象的虚函数表指针找到其虚函数表,进而调用不同的函数。)(只有是虚函数的情况下才会这么做(用虚函数表指针去查虚函数表)。非虚函数直接就调用自己的。)
follow up:
1. 为什么需要虚析构函数?(什么情况下要用虚析构函数?)
在存在类继承并且析构函数中需要析构某些资源时,析构函数需要是虚函数。否则若使用父类指针指向子类对象,在delete时只会调用父类的析构函数,而不能调用子类的析构函数,造成内存泄露。
2. 一个对象访问普通成员函数和虚函数哪个更快?
访问普通成员函数更快,因为普通成员函数的地址在编译阶段就已确定,因此在访问时直接调用对应地址的函数;
而虚函数在调用时,需要首先在虚函数表中寻找虚函数所在地址,因此相比普通成员函数速度要慢一些。
3. 析构函数一定是虚函数吗?
不一定。1. 虚函数效率相对要低一些;2. 有些类并没有子类,没必要用虚析构函数。
4. 内联函数、构造函数、静态成员函数可以是虚函数吗?
都不可以。
内联函数(inline)需要在编译阶段展开(在编译时就已经确定了),而虚函数是运行时动态绑定的,编译时无法展开,因此是矛盾的;
构造函数在进行调用时还不存在父类和子类的概念,父类只会调用父类的构造函数,子类调用子类的,因此不存在动态绑定的概念(先有父类才能有子类,构造父类的时候子类还不存在,子类都还没有怎么可能在父类里动态调用子类);
静态成员函数(static)是以类为单位的函数,与具体对象无关,虚函数是与对象动态绑定的,因此是两个矛盾的概念;
5. 构造函数中可以调用虚函数吗?
可以,但是没有意义,起不到动态绑定的效果。父类构造函数中调用的仍然是父类版本的函数,子类中调用的仍然是子类版本的函数。
6. 简述C++中虚继承的作用及底层实现原理?
虚继承用于解决多继承条件下的菱形继承问题,底层实现原理与编译器相关,一般通过虚基类指针实现,即各对象中只保存一份父类的对象,多继承时通过虚基类指针引用该公共对象,从而避免菱形继承中的二义性问题。
ref:
http://blog.csdn.net/haoel/article/details/1948051
http://songlee24.github.io/2014/09/02/cpp-virtual-table/
http://www.cuiyongjian.com/post-199.html 【分析的很有逻辑】
http://www.guokr.com/blog/469006/
C++虚函数原理的更多相关文章
- C++ 虚函数畅谈
0x01:前言 虚函数是C++里最重要的概念之一,并且是判定C++是否入门的一个热门问题.今天这篇文章简单谈谈虚函数. 0x02:虚函数简介 虚函数可以被子类实现函数所覆盖. virtual是关键字, ...
- c++ 深入理解虚函数
为什么使用虚函数?什么是虚函数?虚函数是为了解决什么问题? 面向对象的三大特征: 封装 多态 继承 普通虚函数 虚析构函数 纯虚函数 抽象类 接口类 隐藏 vs 覆盖 隐藏与覆盖之间的关系 早绑定和晚 ...
- C++虚函数总结
为什么使用虚函数?什么是虚函数?虚函数是为了解决什么问题? 面向对象的三大特征: 封装 多态 继承 普通虚函数 虚析构函数 纯虚函数 抽象类 接口类 隐藏 vs 覆盖 隐藏与覆盖之间的关系 早绑定和晚 ...
- 虚函数列表: 取出方法 // 虚函数工作原理和(虚)继承类的内存占用大小计算 32位机器上 sizeof(void *) // 4byte
#include <iostream> using namespace std; class A { public: A(){} virtual void geta(){ cout < ...
- 【高级】C++中虚函数机制的实现原理
多态是C++中的一个重要特性,而虚函数却是实现多态的基石.所谓多态,就是基类的引用或者指针可以根据其实际指向的子类类型而表现出不同的功能.这篇文章讨论这种功能的实现原理,注意这里并不以某个具体的编译器 ...
- 类虚函数表原理实现分析(当我们将虚表地址[n]中的函数替换,那么虚函数的实现就由我们来控制了)
原理分析 当调用一个虚函数时, 编译器生成的代码会调用 虚表地址[0](param1, param2)这样的函数. 已经不是在调用函数名了. 当我们将虚表地址[n]中的函数实现改为另外的函数, 虚函数 ...
- 漫谈 C++ 虚函数 的 实现原理
文中讲述的原理是推理和探讨 , 和现实中的实现不一定完全相同 . C++ 的 虚函数 , 编译器 会 生成一个 虚函数表 . 虚函数表, 实际上是 编译器 在 内存 中 划定 的 一块 区域, 用于存 ...
- C++虚函数工作原理
一.虚函数的工作原理 虚函数的实现要求对象携带额外的信息,这些信息用于在运行时确定该对象应该调用哪一个虚函数.典型情况下,这一信息具有一种被称为 vptr(virtual table poi ...
- C++ 类的多态三(多态的原理--虚函数指针--子类虚函数指针初始化)
//多态的原理--虚函数指针--子类虚函数指针初始化 #include<iostream> using namespace std; /* 多态的实现原理(有自己猜想部分) 基础知识: 类 ...
随机推荐
- Android_问卷调查
这个是一个简单的问卷调查,对于我这样的初学者可能会绞尽脑汁想尽办法,去实现一个看起来特别简单的功能,我这个是用Intent传参的办法,来实现将前边的调查来进行统计,并记录,之后将这些信息显示到最后一个 ...
- 开发工具 -- PyDev的使用
1.创建PyDev工程 2.创建源文件夹src 3.新建.py文件 其他注意事项 1.设置字体大小 2.显示行号Ctrl + F10 3.编码设置为UTF-8 4.最好将工程创建到默认工作空间 5.总 ...
- 开发工具 -- PyDev 在 Eclipse中的安装
1. 将从sorceforge下载到的PyDev3.4.1解压后放到eclipse的插件目录下F:\APP\IDE\Java\Eclipse\eclipse-java-kepler-SR2-win32 ...
- Python中文分词 jieba
三种分词模式与一个参数 以下代码主要来自于jieba的github,你可以在github下载该源码 import jieba seg_list = jieba.cut("我来到北京清华大学& ...
- 启动mongodb和redis服务器
一.mongodb sudo service mongod start sudo service mongod restart sudo service mongod stop 二.redis red ...
- 编程开发(C/C++&Java&Python&JavaScript&Go&PHP&Ruby&Perl&R&Erlang)
使用Docker快速部署主流编程语言的开发.编译环境及其常用框架,包括C.C++.Java.Python.JavaScript.Go.PHP.Ruby.Perl.R.Erlang等. 在今后采用编程语 ...
- layer相关使用
父子页面传参数 转自:https://blog.csdn.net/babyxue/article/details/76854106 1.父页面打开子页面并向子页面传参数 function setCho ...
- ARM的体系结构与编程系列博客——ARM的历史与应用范围
前言 最近我感觉自己比较浮躁,重来没有好好地沉下心来做一件事情,而且针对自己在专业水平上仍然还有很多欠缺,于是我想我应该为自己做些什么来证明一下自己真的是潜心研究东西的人,于是我萌生了一个想法,真正地 ...
- 深入了解Java虚拟机(2)垃圾收集器与内存分配策略
垃圾收集器与内存分配策略 由于JVM中对象的频繁操作是在堆中,所以主要回收的是堆内存,方法区中的回收也有,但是比较谨慎 一.对象死亡判断方法 1.引用计数法 就是如果对象被引用一次,就给计数器+1,否 ...
- WPF 从文件加载字体
本文告诉大家从文件加载字体.在wpf 使用 fontfamily 显示指定的 ttf 显示字体 假如有字体在 C:\Projects\MyProj\free3of9.ttf ,可以使用 Private ...