多态:指同一个实体同时具有多种形式,即一个名字可以具有多种语义。函数重载、类模板、函数模板等都属于多态性。通俗来说就是接口的多种不同实现方式。

函数绑定:就是函数的入口地址同函数调用相联系的过程。

分为静态绑定和动态绑定。

两者的区别:静态绑定在程序执行前完成,由编译系统或操作系统装入程序计算函数的入口地址;而动态绑定则在执行过程中完成,由程序自身计算函数的入口地址。

静态绑定:在编译阶段决定执行哪个同名的被调用函数。

//静态绑定#include<iostream>#include<stdlib.h>usingnamespacestd;classstudent{public:voidcalfee(){_fee1=1000;}voidprint(){cout<<_fee1<<endl;}protected:int_fee1;};classGraduate:publicstudent{public:voidcalfee(){_fee1=2000;}voidprint(){cout<<_fee1<<endl;}};voidfn(student&x){x.calfee();x.print();}intmain(){students1;Graduateg1;fn(s1);fn(g1);system("pause");return0;}结果:10001000

动态绑定:是由编译系统自动生成的、静态或动态连接的、程序自身激活并执行的过程。在编译阶段不能决定执行哪个同名被调用函数,只在执行阶段才能依据要处理的对象类型来决定执行哪个类的成员函数。

所以要实现动态绑定需要用到虚函数,虚函数是动态绑定的基础。


//动态绑定#include<iostream>#include<stdlib.h>usingnamespacestd;classstudent{public:virtualvoidcalfee(){_fee1=1000;}virtualvoidprint(){cout<<_fee1<<endl;}protected:int_fee1;};classGraduate:publicstudent{public:voidcalfee(){_fee1=2000;}voidprint(){cout<<_fee1<<endl;}};voidfn(student&x){x.calfee();x.print();}intmain(){students1;Graduateg1;fn(s1);fn(g1);system("pause");return0;}结果:10002000

下面分析一下虚函数

虚函数:也是类的一种成员函数,并且不能是静态成员函数。

虚函数的作用是实现动态绑定,也就是在程序的运行阶段动态的选择合适的成员函数。从而实现多态性

设置虚函数的一写注意事项:

1、只有类的成员函数才能声明为虚函数。因为虚函数只适用于有继承关系的类对象,所以普通函数不能声明为虚函数。

2、静态成员不能是虚函数,因为静态成员不受限于某个对象。

3、内联函数不能是虚函数,因为内联函数不能在运行中欧诺个动态的确定其位置。即使虚函数在类的内部定义,编译时仍将其看做是非内联的。

4、构造函数不能是虚函数,因为构造时对象还是一片未定型的空间。只有在构造完成后,对象才能成为一个类的名副其实的实例。

5、析构函数可以是虚函数,而且通常声明为虚函数。目的在于:使用delete删除一个对象时,确保析构函数能够被正确运行。因为设置虚析构函数后,可以利用动态绑定方式选择析构函数。


下面程序演示了析构函数在有些情况下必须设置为虚函数

classA{public:A(){cout<<"A()"<<endl;}virtual~A(){cout<<"~A()"<<endl;}};classB:publicA{private:char*_buf;public:B(inti){_buf=newchar[i];cout<<"B()"<<endl;}virtual~B(){delete[]_buf;cout<<"~B()"<<endl;}};voidfun(A*pa){deletepa;}intmain(){A*pa=newB(10);fun(pa);system("pause");return0;}结果:A()B()~B()~A()如果将~A()不定义为虚函数,则结果为:~A()


纯虚函数:无函数体的一种特殊的虚函数。

其声明的格式为:virtual 类型 函数名(参数表)= 0;

抽象类:至少有一个纯虚函数的类。

作用:将有关类组织在一个继承层次结构中,由它提供一个公共的根,相关的子类都是从这个根派生出来的。

抽象类的使用规定:

1、抽象类只能用作其他类的基类,不能建立抽象类对象。

2、抽象类不能用作参数类型、函数返回类型或显示转换类型

3、可以定义抽象类的指针和引用,此指针可以指向它的派生类,从而实现多态。

classA//抽象类{public:A(){cout<<"A()"<<endl;}virtual~A(){cout<<"~A()"<<endl;}virtualvoidfun()=0;};classB:publicA{public:B(){cout<<"B()"<<endl;}virtual~B(){cout<<"~B()"<<endl;}voidfun(){cout<<"B::fun()"<<endl;}};classC:publicA{public:C(){cout<<"C()"<<endl;}virtual~C(){cout<<"~C()"<<endl;}voidfun(){cout<<"C::fun()"<<endl;}};intmain(){A*arr[2];Bb;Cc;arr[0]=&b;arr[0]->fun();arr[1]=&c;arr[1]->fun();system("pause");return0;}