我对虚函数的理解

       虚函数是具备这样一种能力的函数:能够在知道少量信息的情况下判断出自己的所属者,进而调用所属者里对应的函数。以虚析构函数为例解释下,当我们释放一个用基类的指针指向派生类的对象时(Base*pBase = objChild;delete pBase),这时候如果析构函数不是虚函数,就不能正确识别对象类型从而不能正确调用析构函数;而如果析构函数是虚函数的话,当delete 基类指针时,虚析构函数能够准确判断出自己的所属对象为派生类对象,从而去调用派生类的析构函数,当然了当派生类的析构函数调用完后会继续调用基类的析构函数。 

        正是虚函数所具备的这种能力使C++具有了多态特性,当通过指向派生类对象的基类指针进行调用虚函数(派生类对其重写)时,该虚函数能准确判断出自己的所属对象从而调用所属对象里面所重写的函数。

        从上面的讨论我们可以得知虚函数所属的对象就如同自己的亲生父母,因此,构造函数一定不可能是虚函数,因为连父母还没有的时候何来的孩子--虚函数呢?这样说或许不够严谨,我们可以从存储空间的角度来分析下构造函数为什么不能为虚,我们知道虚函数对应一个包含着所有虚函数地址信息的vtable,每一个对象都保存着一个指向vtable的指针来调用其内的虚函数。问题出来了,如果构造函数是虚的,就需要通过对象里的指向vtable的指针来调用,可是对象还没有实例化,也就是内存空间还没有,怎么根据指向vtable的指针去寻找构造函数呢?所以构造函数不能是虚函数,不能使构造函数放到vtable中去被调用。
 
虚函数与非虚函数相比是有一定的代价,在内存和执行速度方面是有一定成本的,包括:
1.对于对象来言将会增大其存储量,增大量为存储虚函数表指针的大小;
2.对于类来言,编译器都会创建一个虚函数地址表来保存虚函数的地址信息,虚函数的调用都要通过虚函数表查找;
3.对于每一个虚函数调用,都需要执行一次额外的操作,即到虚函数表中查找地址。
虽然非虚函数比虚函数效率高,但不具备动态绑定的能力。
 


你可能感兴趣的:(C++,虚函数,多态)