三、作用
虚函数的作用是允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用访问基类和派生类中的同名函数。
四、使用方法
《由虚函数实现的动态多态性就是:同一类族中不同类的对象,对同一函数调用做出不同的响应》
(1):在基类中用virtual声明成员函数为虚函数。这样就可以在派生类中重新定义次函数,为它赋予新的功能,以此方便被调用。在类的外部定义虚函数时不用加virturl.
(2):在派生类中重新定义此函数时,要求函数名,函数类型,函数的参数个数和类型全部和基类的虚函数相同,并根据派生类重新来定义该函数体。
【C++规定--如果基类中的一个成员函数被声明为虚函数后,其派生类的同名函数也会自动的成为虚函数,因此派生类重新声明该函数时可以不加virtual,但为了程序更加清晰易读,一般都加上】
而如果在派生类中没有对基类的虚函数进行重新定义,则此时派生类只是简单的继承其基类的虚函数。
(3):定义一个指向基类对象的指针变量,并使他指向同意类族中需要调用该函数的对象,通过这个变量调用此虚函数时,这个时候调用的就是指针变量指向的对象中的同虚函数同名的同名函数。通过虚函数和指向基类对象的指针变量的配合使用,就能够方便的调用同一类族中不同类的同名函数。如果指针不断的指向同一类族中的不同的对象,就能不断的调用这些对象中的同名函数。(就像打的时,不断告诉司机要去的地儿,然后司机师傅就会把你送到你想去的地方!!)
五、补充说明:
有时在基类中定义的非虚成员函数也会在派生类中被重新定义,但这个行为并不是多态性行为,只是函数的重载。如果用基类指针调用该函数,则系统会默认调用基类部分的成员函数;如果用派生类指针调用该函数,则系统会调用派生类对象中的成员函数。
函数重载处理的是同一层次的同名函数的问题,而虚函数解决的是不同派生层次的同名函数的问题。此外,同一族类的虚函数的首部是相同的,而函数重载时函数的首部使不同的(参数个数和类型不同)。
六、静态关联和动态关联
编译系统在程序编译的过程中,确定类对象和函数名的过程成为关联,即--确定调用的具体对象的过程成为关联。一般来说,关联是指把一个标识符和一个存储地址联系起来。
|----静态关联:在编译时即可确定其调用的虚函数属于哪一类.(如:函数重载和通过对象名调用的虚函数),也称早期关联。
关联 |
|-----动态关联:在程序的运行过程中,把虚函数和类对象绑定在一起(通过基类指针和对象调用虚函数)也称为滞后关联。
七、虚函数的使用注意说明:
(1)、只能用virtual声明类的成员函数,而不能用它来声明类外的普通函数,因为虚函数的作用是允许在派生类中对基类的虚函数进行重新定义,显然它只能用于类的继承层次结构中。
(2)、只要类中的一个成员函数被定义为虚函数后,那么同一个类族的类中就不能再定义一个 非virtual的但与该虚函数具有相同参数和函数返回值的同名函数
(3)、如果成员函数所在的类为基类,并且后期需要为该函数添加或是更改其功能,需要将其声明为虚函数,否则不用。
(4)、考虑成员函数的调用是通过 对象名 还是 通过基类指针或引用去访问。若是后者需要将其声明为虚函数
(5)、有时定义虚函数时并不定义其函数体,具体的功能是留给派生类去添加实现的。
(6)、使用虚函数,系统是会有一定的空间开销的,当一个类带有虚函数的时候,编译系统会为该类构造一个虚函数表,它是一个指针数组,里边存放了每一个虚函数的入口地址。