浅析C++中的虚函数
本文导语: 一、定义定义:在某基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数。 语法:virtual 函数返回类型函数名(参数表) { 函数体 } 用途:实现多态性,通过指向派生类的基类指针,访问派生类中同名覆...
一、定义
定义:在某基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数。
语法:virtual 函数返回类型函数名(参数表) { 函数体 }
用途:实现多态性,通过指向派生类的基类指针,访问派生类中同名覆盖成员函数 虚函数必须是基类的非静态成员函数,其访问权限可以是protected或public。
定义为virtual的函数是基类期待派生类重新定义的,基类希望派生类继承的函数不能定义为虚函数。
二、作用
虚函数的作用是实现动态联编,也就是在程序的运行阶段动态地选择合适的成员函数,在定义了虚函数后,可以在基类的派生类中对虚函数重新定义,在派生类中重新定义的函数应与虚函数具有相同的形参个数和形参类型。以实现统一的接口,不同定义过程。如果在派生类中没有对虚函数重新定义,则它继承其基类的虚函数。 当程序发现虚函数名前的关键字virtual后,会自动将其作为动态联编处理,即在程序运行时动态地选择合适的成员函数。虚函数是C++多态的一种表现。
使用虚函数,我们可以灵活的进行动态绑定,当然是以一定的开销为代价。如果父类的函数(方法)根本没有必要或者无法实现,完全要依赖子类去实现的话,可以把此函数(方法)设为virtual 函数名=0 我们把这样的函数(方法)称为纯虚函数如果一个类包含了纯虚函数,称此类为抽象类。
我们只需在把基类的成员函数设为virtual,其派生类的相应的函数也会自动变为虚函数。
三、动态绑定过程
表面点来说,虚函数是根据调用它的指针或引用所指向或绑定的对象的类型来调用绑定或指向的类型所定义的虚函数版本。
由于类中有虚函数存在,所以编译器就会为这个类插入一段你不知道的数据,并为它创建一个表。那段数据叫做vptr指针,指向那个表。那个表叫做vtbl,每个类都有自己的vtbl,vtbl的作用就是保存自定义为virtual的函数是基类期待派生类重新定义的,基类希望派生类继承的函数不能定义为虚函数己类中虚函数的地址,我们可以把vtbl形象地看成一个数组,这个数组的每个元素存放的就是虚函数的地址。
调用虚函数时,首先是取出vptr的值,这个值就是vtbl的地址,再根据这个值来到vtbl这里,取出vtbl中相应的slot里的值,这个值就是所在调用的虚函数的地址了,最后调用这个函数。现在我们可以看出来了,只要vptr不同,指向的vtbl就不同,而不同的vtbl里装着对应类的虚函数地址,所以这样虚函数就可以完成它的任务。
四、纯虚函数
在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用。
纯虚函数可以让类先具有一个操作名称,而没有操作内容,让派生类在继承时再去具体地给出定义。凡是含有纯虚函数的类叫做抽象类。这种类不能声明对象,只是作为基类为派生类服务。除非在派生类中完全实现基类中所有的的纯虚函数,否则,派生类也变成了抽象类,不能实例化对象。在函数形参后面写上=0以指定纯虚函数。