C++面向对象的三个特性,封装继承多态。在继承的关系中,所有的东西都可以被继承下来,如数据可以被继承下来在内存,而函数的继承则是继承调用权。
虚函数主要是通过虚函数表来实现,每个类都有自己的虚表,当你创建一个对象时候,对象的首地址处存放指向虚表的指针。下图是虚表的概念,其实不难。当子类继承父类的时候,会继承父类的虚函数表,这个时候如果在子类中重写父类中的虚函数,那么虚函数表中指向的函数地址也会发生改变,如果没有发生重写,则会指向原来的地址,以这种方式实现运行时候多态。
如果希望禁止子类重写虚函数,则需要声明final虚函数,被声明为 final 的类不能用作基类。
下面是以问题的方式来进行虚函数相关的学习。
1、虚函数如何实现的?会变慢吗?
虚函数是通过虚函数表实现的,每个类都有自己的虚表,对象的首地址处存放有指向虚表的指针。当具体调用哪个虚函数可以在编译期间确定的时候,虚函数不一定更慢。
2、构造函数、析构函数、重载运算符函数可以是虚函数吗?类成员函数模板可以是虚函数吗?
析构函数和重载运算符函数都可以是虚函数,但是构造函数不能是虚函数,因为构造函数是用来创建对象的,在创建对象期间,存放虚函数地址的虚表还没有创建完成,如果直接调用虚函数会引发异常。类成员函数模板不能是虚函数,因为C++在链接前是不知道成员函数模板被实例化多少次的,这就会导致编译器无法在编译期间确定虚表的大小。
3、为什么把析构函数定义为虚函数
如果释放父类指针指向子类对象的时候,析构函数不设置为虚函数就会只析构基类而不析构子类。会造成内存泄露。