关于虚函数的一些总结
Last updated on 8 months ago
说到多态又可以联想到虚函数,虚函数又有很多相关问题,这次做个小总结
1 . 什么是虚函数
虚函数在有多态的前提下才有的特性,现在问题是多态是什么?
多态可以分为:
静态多态:函数重载,根据参数不同,从而调用不同的函数(这里不做重点介绍)
动态多态: 根据操作的对象不同,从而调用不同的函数(使用虚函数实现)
总的来说: 同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结
现在看下动态多态是怎么使用:
1 |
|
基类用 virtual 声明了函数,用基类的指针指向不同的派生类,然后基类的指向的函数也有不同的效果
那这个的原理是怎样的呢?即虚函数如何实现的?
如果一个带有虚函数的类的大小他的大小是多大呢?
先不说为什么空类大小为1 ,我们先说带有虚函数的类大小为4, 因为带有虚函数的类有一个指向函数数组的指针,而指针是4个字节的,指针指向的数组可以函数,那么能否直接自己直接通过指针来调用虚函数呢? 答案是可以的
如上图所示,用通过 base 实例化的 b地址 可以调用类中的虚函数,通过偏移值的不同,调用不同的函数 ,可以看出 实例化后的 b是有个指针指向一个指针数组 ,就该base类而言,内存布局如下:
现在我们知道了虚函数表的如何存在的,那如何通过这个实现多态的呢?
用一个基类的指针指向派生类时候,如果派生类中有函数重载了父类的虚函数,则会替换虚函数表中对应的函数
就是说 : 假如派生类也有函数 f(); 此时 虚表中 f()的函数地址 会被 派生类的 f() 函数替换(也称为动态联编)
与基类指针 指向 f() 时,执行的是派生类的 f()
大致上的原理 就这样,其实还有多细节没有补充,想着通过反汇编来看下动态联编是怎么实现,后续再来吧..
一些虚函数的问题
什么函数不能声明为虚函数
构造函数
虚表指针的初始化时在构造函数进行的,而虚函数需要放到虚表中。在调用虚函数前,必须首先知道虚表指针,所以不行
普通函数
虚函数需要在继承多态下使用才有意义
静态函数
静态函数可以直接调用不需要指针
内联函数
内联函数属于静态联编,即是编译阶段就确定调用哪个函数了,虚函数是动态联
友元函数
有元函数不支持继承