C++为了实现多态性,提供了静态绑定(早捆绑或者叫做编译期绑定)和动态绑定(晚捆绑)两种机制。
静态绑定中包括:
1、函数重载
2、运算符重载
3、子类继承父类时,父类中的函数没有添加virtual关键字(非虚函数),父类指针指向子类的地址时,调用和父类同名的函数则会默认调用父类的同名函数,子类同名函数的不会被调用。因为在程序编译阶段,编译系统自动将基类的同名函数的函数体和父类指针指向的函数名进行了绑定。
虚函数的定义:
virtual <类型><函数名>(<参数列表>)
{
}
虚函数一定是成员函数,非成员函数是不能定义为虚函数的,并不是所有的成员函数都可以定义为虚函数,比如静态成员函数和构造函数。析构函数在某些情况下可以定义为虚函数。
虚函数可以定义在类内和类外。
虚函数的作用:
虚函数的目的就是告诉编译器在编译的时候先不要进行静态绑定,等到程序执行的时候再进行选择。其实这就是动态绑定的机制,动态绑定必须通过虚函数才能实现,没有虚函数的多态都是静态绑定。
在类的继承关系中,不同层次的类中可以出现相同的名字,成员数据和同名的函数。虽然名字相同,但是他们的实现或者代表的意义是不一样的。因此,如果基类中的成员和子类的成员存在同名的情况,C++编译系统将采取同名覆盖的原则来处理因为同名而存在的冲突问题。
虚函数的特征:
虚函数具有一个重要的特点就是继承性。在基类中声明的虚函数,在子类中函数声明完全相同的函数为虚函数。声明该虚函数时可以使用virtual关键字,也可以不使用。因为当将基类中的某一个成员函数声明为虚函数后,子类中的同名函数自动称为虚函数。但是建议还是加上virtual关键字,因为这样可以提高程序的可阅读性。
虚函数的默认参数:
1、当基类指针或者引用调用虚函数时,如果基类中的虚函数含有默认值,那么子类中的虚函数默认值将无效,不起任何作用。
2、如果子类对象直接调用虚函数,那么会直接使用子类中的虚函数默认值。
静态绑定和动态绑定的区别:
1、静态绑定是根据编译时声明的变量类型,来决定调用的是哪个类型的函数。
2、动态绑定是根据运行时实际赋给变量的类型,来决定调用的是基类或者是子类的函数。
总结:
虚函数是实现动态绑定的重要形式,要想实现动态绑定必须实现虚函数,没有虚函数参与实现的多态性都不是动态绑定。但是,虚函数不是实现动态绑定的唯一条件,实现动态绑定还与虚函数的访问方式有关。
只有通过对象的指针或者引用(基类指针的地址指向子类的地址)才能调用虚函数实现动态绑定。否则。即使使用了虚函数,如果是通过对象直接调用或者通过基类进行调用,还是静态绑定。