多态
即同一接口,不同形态(函数名相同,参数不同,调用的函数不同,展示的形态不同)
- 静多态(早绑定/联编 静态绑定/联编)
(编译阶段确定函数的调用 函数重载 模板)
- 动多态(晚绑定/联编 动态绑定/联编)
(运行阶段确定函数的调用 虚函数机制)
- 宏多态
(预编译阶段确定函数的调用)不建议使用 高级宏:内联函数
联编
程序调用函数时,将使用哪个可执行代码块?编译器负责回答这个问题。将源代码中的函数调用解释为执行特定的函数代码块,被称为函数联编。
在编译过程中进行联编称为静态联编(static binding),又称静态绑定。然而,虚函数的存在使得这项工作变得更加困难,使用哪一个函数是不能在编译时期确定的,因为编译器不知道用户将选择哪种类型的对象。所以,编译器必须能够在程序运行时选择正确的虚函数的代码,这称为动态联编/绑定。
虚函数
什么是虚函数(virtual)
即函数名前加了virtue关键字的函数
- virtual放在函数的返回值前面,用于表示该成员方法为虚方法
- 基类(父类)虚函数前必须写;子类可以省略。
- virtual只能出现在类内部而不能用于类外部的函数定义
为什么设计虚函数
- 我们知道派生类会拥有基类的定义的函数,但是如果对于某些函数,我们希望派生类各自定义适合派生类自己的版本的函数,于是基类就可将此函数定义为虚函数,让派生类各自实现自己功能版本的函数。为动多态提供支持。
举例:
Base *base; // 定义基类指针
Derive derive; // 定义派生类对象
base = &derive; // 基类指针指向派生类对象
base->function();
结果证明:那么如果在基类中没有将function()声明为虚的(virtual),那么base->function()将根据指针类型(Base *)调用Base::function()。指针类型在编译时已知,因此编译器在编译时,直接将function()关联到Base::function()。总之,编译器对非虚方法使用静态联编。
而使用虚方法之后:
结果证明:如果在基类中将function()声明为虚的,则base->function()将根据对象类型(Derive)调用Derive::function()。对象类型为Derive,但通常只有在程序运行时才能确定对象的类型。所以编译器生成的代码将在程序执行时,根据对象类型将function()关联到Derive::function()或Base::function()。总之,编译器