虚函数多态机制可以让成员函数操作一般化,用基类指针指向不同派生对象时,基类指针可以调用其派生对象的虚函数成员。
1.虚函数
C++的虚函数作用主要是运行时多态,父类中提供虚函数的实现,为子类提供默认的函数实现。子类可以重写父类的虚函数,以实现子类的特殊化。
多态的关键之处,是通过一切指向基类的指针或引用来操作对象。
2.纯虚函数
C++中的包含纯虚函数的类是抽象类,抽象类不能new出对象,只有实现了纯虚函数的子类才能new出对象。即只提供申明,没有实现,是对子类的约束,是“接口继承”。
3.普通函数
普通函数是静态编译的,没有运行时多态,只会根据指针或引用的“字面值”类对象,调用自己的普通函数,普通函数是父类为子类提供的强制实现。
4.综合实例
#include <iostream> using namespace std; class A { public: virtual void out1()=0; ///由子类实现 virtual ~A(){}; virtual void out2() ///默认实现 { cout<<"A(out2)"<<endl; } void out3() ///强制实现 { cout<<"A(out3)"<<endl; } }; class B:public A { public: virtual ~B(){}; void out1() { cout<<"B(out1)"<<endl; } void out2() { cout<<"B(out2)"<<endl; } void out3() { cout<<"B(out3)"<<endl; } }; int main() { A *ab=new B; ab->out1(); ab->out2(); ab->out3(); cout<<"************************"<<endl; B *bb=new B; bb->out1(); bb->out2(); bb->out3(); delete ab; delete bb; return 0; }
执行结果:
B B A ****** B B B
即静态编译的函数是根据指针的类型调用的,运行时多态的函数是根据new出的对象调用的。
虚函数的目的是,不同父类指针指向同一子类实例,能够调用到实际的函数。
5.虚函数的实现机制
C++的虚函数是通过一张虚函数表来实现的,这个表的内容就是虚函数的地址表,当我们用父类指针去操作一个子类的时候,根据这张表上的函数地址来调用函数。
在类被继承时,如果某虚函数没有被覆盖,那么虚函数表中会增加原来没有的函数,而原来父类中虚函数的也依然存在。如果继承时,某虚函数被覆盖,那么虚函数表中对应的函数地址将被改变。在多重继承时,每个父类都有自己的虚函数表。
这样做就是为了解决不同的父类类型的指针指向同一子类实例,能够得到调用到实际函数。
6.虚函数表的安全性问题
通过父类的指针访问子类的虚函数会导致编译出错
如果虚函数是private或者protected,那么可以通过虚函数表访问这些函数
OK,See You Next Chapter!