什么是多态性?
不同的对象,接受相同的消息,产生不同的动作。即同样的接口访问功能不同的函数。
C++实现的多态性:
编译时的多态性:
- 函数重载
- 运算符重载
- 模板
运行时的多态性
- 借助虚函数
静态联编和动态联编
- 静态联编:在程序被编译时进行联编。
优点:程序执行快,但灵活性较小 - 动态联编:编译时无法确定要调用的函数,在程序运行时联编。
优点:灵活度高,但程序执行慢。
动态联编是实现运行时多态的关键因素
虚函数
在函数前加上virtual
关键字。虚函数是成员函数,而且是非static
函数,包含虚函数的类成为多态类。
virtual
关键字的作用:指示C++编译器对该函数的调用进行动态联编。
通过对象名调用虚函数是静态联编方式
只有当访问虚函数是通过基类指针时才可获得运行时的多态性。
虚函数和重载函数的比较
形式上:
- 重载函数要求函数有相同的函数名称,并有不同的参数序列。
- 而虚函数要求函数名称、返回值、参数序列 完全相同,即有完全相同的函数原型。
函数类型上:
- 重载函数可以是成员函数和非成员函数。
- 虚函数只能是成员函数。
调用方式上:
- 对重载函数的调用是以所传参数序列的差别(参数个数或类型的不同)作为调用不同函数的依据。
- 虚函数是根据对象的不同去调用不同类的虚函数。
虚函数小结:
- 如果某类中的一个成员函数被说明为虚函数,这就意味着该成员函数在派生类中可能有不同的实现。
- 为了实现运行时的多态性,调用虚函数应该通过第一次定义该虚函数的基类对象指针
- 只有通过指针或引用标识对象来操作虚函数时,才对虚函数采取动态联编方式。
- 如果采用一般类型的标识对象来操作虚函数,则将采用静态联编方式调用虚函数。
- 构造函数不能是虚拟的,但析构函数可以是虚拟的。
- 友元函数不能是虚函数,因为友元函数不是成员函数。
纯虚函数
纯虚函数是指在基类中声明但是没有定义的虚函数,而是设置函数值等于零。
virtual type func_name(parameter list) =0;
通过将虚函数声明为纯虚函数可以强制在派生类中重新定义虚函数。
如果没有在派生类中重新定义,编译器将会报告错误。
抽象类
- 包含有纯虚函数的类成为抽象类。
- 不能说明抽象类的对象,只能说明指向抽象类的指针,一个抽象类只能作为基类来派生其他的类
- 抽象类的指针用于指向该抽象类的派生类的对象。