1、c++虚函数原理:
虚函数:指向基类的指针在操作它的多态类对象时,会根据不同的类对象,调用其相应的函数,这个函数就是虚函数。
c++中虚函数表的作用主要是实现了多态的机制。
多态:就是用父类的指针指向其子类的实例,然后通过父类的指针 根据不同的子类对象 调用实际子类的成员函数,这种方法既不需要改动代码就可以让父类指针执行很多子类的操作,这就是虚函数的实现机制。
class Base
{
public:
virtual void Func1()
{
//Func1的实现代码
}
virtual void Func2()
{
//Func2的实现代码
}
//...
virtual void FuncN()
{
//FuncN的实现代码
}
};
class Derived : public Base
{
public:
virtual void Func1()
{
//Func2覆盖Base类的Func1代码
}
virtual void FuncN()
{
//FuncN覆盖Base类的FuncN代码
}
};
由于这两个类中有虚函数存在,编译器将为实现了虚函数的基类和覆盖了虚函数的派生类分别创建一个虚函数表(Virtual Function Table,VFT)。也就是说Base和Derived类都有自己的虚函数表。
虚函数表的作用就是保存自己类中虚函数的地址,我们可以把VFT形象地看成一个数组,这个数组的每个元素存放的就是虚函数的地址
实例化这些类的对象时,将创建一个隐藏的指针vP*,它指向相应的VFT。可将VFT视为一个包含函数指针的静态数组,其中每个指针都指向相应的虚函数。Base类和Derived类的虚函数表如下图所示:
验证虚函数表的存在可以通过比较同一个类,一个包含虚函数,一个不包含,对比其大小。
虚函数表:
类的虚函数表是一块连续的内存,每个内存单元中记录一个JMP指令的地址
注意的是,编译器会为每个有虚函数的类创建一个虚函数表,该虚函数表将被该类的所有对象共享。类的每个虚成员占据虚函数表中的一行。如果类中有N个虚函数,那么其虚函数表将有N*4字节的大小。
虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。在这个表中,主要是一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其真实反应实际的函数。这 样,在有虚函数的类的实例中这个表被分配在了这个实例的内存中,所以,当用父类的指针来操作一个子类的时候,这张虚函数表就显得由为重要了,它就像一个地 图一样,指明了实际所应该调用的函数。
编译器应该是保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证取到虚函数表的有最高的性能——如果有多层继承或是多重继承的情况下)。 这意味着可以通过对象实例的地址得到这张虚函数表,然后就可以遍历其中函数指针,并调用相应的函数。
通过虚函数表指针VPTR调用重写函数是在程序运行时进行的,因此需要通过寻址操作才能确定真正应该调用的函数。而普通成员函数是在编译时就确定了调用的函数。在效率上,虚函数的效率要低很多。
参考博文: