虚函数是面向对象编程函数的一种特定形态,是C++用于实现多态的一种有效机制。
多态
C++的多态可以分为静态多态和动态多态。函数重载和运算符重载实现的多态属于静态多态,而通过虚函数可以实现动态多态。实现函数的动态联编其本质核心则是虚表指针与虚函数表。
虚函数
指向基类的指针在操作它的多态类对象时,会根据不同的类对象调用其相应的函数,这个函数就是虚函数,虚函数用virtual修饰函数名。虚函数的作用是在程序的运行阶段动态地选择合适的成员函数。在派生类中重新定义的函数应与虚函数具有相同的形参个数和形参类型,(参数类型的顺序也要一致),以实现统一的接口。如果在派生类中没有重新定义虚函数,则它继承基类的虚函数。
注意
(1)只需在声明函数的类体中使用关键字virtual将函数声明为虚函数,在定义函数时不需要
(2)将基类中某一成员函数声明为虚函数后,派生类中的同名函数自动成为虚函数
(3)如果类(基类和派生类)中声明了某成员函数为虚函数,则类中不能再出现与之相同的非虚函数
(4)非类的成员函数不能定义为虚函数,全局函数以及类的静态成员函数(因为调用类的静态成员函数不需要实例,但调用虚函数需要一个实例)和构造函数(因为构造函数是在对象完全构造之前运行的,构造函数是初始化虚表指针,而当要调用虚函数时需要知道虚表指针,存在矛盾,但构造函数里是可以调用虚函数的)、内联函数也不能定义为虚函数,但一般将析构函数定义为虚函数(如果不把析构函数定义为虚函数,当用基类指针delete时,无法调用派生类的析构函数,派生类部分无法析构)
(5)指针声明不调用构造函数
编译器发现一个类中有虚函数时,会立即为此类生成一个虚函数表,虚函数表的各表项为指向对应虚函数的指针。编译器还会在此类中隐含插入一个指针vptr指向虚函数表。另外在调用类的构造函数时,指向基础类的指针此时已经变成指向具体类的this指针,这样依靠this就可以得到正确的table,这样才能真正与函数体进行连接,这就是动态联编,实现多态的基本原理。
C++中继承、虚函数、纯虚函数分别指什么?
继承:在C++中继承的使用方式如下:class 派生类名:public/protected/private 基类名{}。是指一种事物自动获得另一种事物的全部东西(属性,能力)。
虚函数:用virtual修饰的函数就是虚函数,它实现了类的多态。以基类对象的身份调用虚函数,如果对象是派生类,派生类的对应函数就会被调用,从而可以实现通过完全相同的调用形式让不同的类型的对象做出自己不同的响应。
纯虚函数:是一种特殊的虚函数
是否可以把每个函数都声明为虚函数呢?
虽然虚函数很有效,但是不可以把每个函数都声明成虚函数。因为使用虚函数要付出内存代价,每个虚函数的对象在内存中都必须维护一个虚函数表,额外产生了系统开销。