虚函数

来源:互联网 发布:大数据与经济发展 编辑:程序博客网 时间:2024/06/06 01:02

虚函数的使用方法:

1. 在基类中使用virtual声明成员函数为虚函数 :

      类内声明:virtual [类型]函数名([参数表列])

2. 在类外定义虚函数时,不再加virtual

3.效果

派生类根据需要可以重新定义函数体(函数覆盖),使用虚函数提高了程序的可扩充性;

成员函数被声明为虚函数后,其派生类中函数覆盖的同名函数自动定义为虚函数;

若虚函数在派生类中未重新定义,则派生类简单地继承其直接基类的虚函数;

指向基类的指针,当指向派生类对象时,则可以调用派生类的方法。这是最大最好最直接的好处!!!!

解释:当有了这种函数覆盖的虚函数之后,就可以用指向基类的指针调用派生类的方法。这个方法就是基类中的虚函数、经过函数覆盖,在派生类中也有了定义。

一旦在基类中一个成员函数被声明为虚函数,那么从这个类中派生的子类,从子类派生出的子类,等等等等,与这个函数同名的覆盖函数,都是虚函数。



对于上面这个程序来说,pc=&cy1也就是说pc又指向了派生类的对象,但是pc->area()执行的依旧是基类中的函数;而我们希望了是既然pc指向了圆柱Cylinder对象了,那么就应该执行派生类中的函数,


上面这个程序,用了虚函数之后,就可以实现我们的目的。


静态关联与动态关联

关联:

通过关联,把一个标识符与一个存储地址联系起来

通过关联,可以把一个函数名与一个类对象捆绑在一起(其中,函数名就是一个标识符,每一个类对象都有一个存储地址)


静态关联:

函数重载和通过对象名调用的(虚)函数,在编译时 就可以确定其调用的(虚)函数属于哪一个类,又称为早期失联。



动态失联:

通过基类指针与虚函数,在运行阶段确定关联关系。

动态关联提供动态的多态性,即运行阶段的多态性。

也成为滞后关联。

(如果基类指针指向的是基类对象,那么执行的是基类中的(虚)函数;但是如果基类指针指向的是派生类对象,那么执行的就是派生类中的函数。)


虚函数的更深刻理解:

1. 虚函数只能是类的成员函数,而不能将类外的普通函数声明为虚函数;

虚函数的作用是允许在派生类中对基类的虚函数重新定义(函数覆盖),只能用于类的继承层次结构中。

2. 排他性 

一个成员函数被声明为虚函数后,在同一类族中(继承层次中的类)的类就不能再定义非virtual,但与该虚函数具有相同的参数(包括个数与类型)和函数返回值类型的同名函数。

3. 使用虚函数,系统会有少量的空间开销

当一个类带有虚函数时,编译系统会为该类构造一个虚函数表(一个指针数组),用于存放每个虚函数的吐口地址。


何时用虚函数:

1. 成员函数所在类是否会当基类

2. 成员函数在类被继承 后有无可能被更改功能

如果希望更改其功能的,一般应该在基类中将其声明为虚函数;

如果成员函数在类被继承后功能不需或者不能修改,或派生类用不到该函数,则不声明为虚函数。

3. 对成员函数的调用时通过对象名(这通过静态关联,静态多态性就可以)还是通过基类指针或引用去访问(虚函数)

4.定义虚函数时,有时候可以不定义其函数体,即函数体是空的,只等着被继承 。

它的作用只是定义了一个虚函数名,具体功能留给派生类去添加--------纯虚函数


只有通过基类指针或引用间接指向派生类子类型时,多态性才会起作用。当成员函数是虚拟的时候,通过一个类对象(指针或引用)而被调用的该成员函数,是在该类对象的动态类型中被定义的成员函数。但是一个类对象的静态和动态类型是相同的,所以虚拟函数机制只在使用指针和引用的时候才会起作用。


重点: 如果子类覆盖的是基类的虚函数,可以用来实现多态。

    当子类重新定义基类的虚函数之后,基类指针可以根据赋给它不同子类指针动态的调用子类中的虚函数,可以做到动态绑定,这就是动态多态。


子类覆盖基类函数的特征

(1)函数名相同、参数相同、返回值相同

(2)如果基类函数是虚函数,子类覆盖虚函数可以实现多态