(都是自己在学习中整理的,有不对的请多多指教~~~)
1.
虚函数和纯虚函数可以定义在同一个类中,含有纯虚函数的类被称为抽象类,而只含有虚函数的类不能被称为抽象类。
2.虚函数可以被直接使用,也可以被子类重载以后,以多态的形式调用,而纯虚函数必须在子类中实现该函数才可以使用,因为纯虚函数在基类有声明而没有定义。
3.虚函数和纯虚函数都可以在子类中被重载,以多态的形式被调用。
4.虚函数和纯虚函数通常存在于抽象基类之中,被继承的子类重载,目的是提供一个统一的接口。
5.虚函数的定义形式:virtual { };纯虚函数的定义形式:virtual { } = 0;在虚函数和纯虚函数的定义中不能有static标识符,原因很简单,被static修饰的函数在编译时要求前期绑定,然而虚函数却是动态绑定,而且被两者修饰的函数生命周期也不一样。
虚函数充分体现了面向对象思想中的继承和多态性这两大特性,在C++语言里应用极广。比如在微软的MFC类库中,你会发现很多函数都有virtual关键字,也就是说,它们都是虚函数。难怪有人甚至称虚函数是C++语言的精髓。
定义纯虚函数就是为了让基类不可实例化,因为实例化这样的抽象数据结构本身并没有意义或者给出实现也没有意义。
纯虚函数只是一个接口,是个函数的声明而已,它要留到子类里去实现。
虚函数在子类里面也可以不重载的;但纯虚必须在子类去实现,这就像Java的接口一样。通常我们把很多函数加上virtual,是一个好的习惯,虽然牺牲了一些性能,但是增加了面向对象的多态性,因为你很难预料到父类里面的这个函数不在子类里面不去修改它的实现。
请谈一下你对C++中虚函数的认识,并解释纯虚函数的用途。
首先,C++通过虚函数实现多态。“无论发送消息的对象属于什么类,他们均发送具有同一形式的消息,对消息的处理方式可能随接收消息的对象而变”的处理方式被称为多态性。在某个基类上建立起来的类的层次构造中,可以对任何一个派生类的对象中的同名过程进行调用。而被调用的过程提供的处理可以随其所属的类而发生改变。
虚函数首先是一种成员函数,它可以在该类的派生类中被重新定义并被赋予另外一种处理功能。
虚函数允许派生类取代基类所提供的实现。编译器确保当对象为派生类时,即派生类的实现总是被调用,即使对象是使用基类指针访问而不是派生类的指针。这样就允许基类的算法被派生类取代,即使用户不知道派生类的细节。
派生类可以完全取代基类成员函数(覆盖),也可以部分取代基类成员函数(增大),后者还可由派生类成员函数调用基类成员函数来完成。
相比而言,虚成员函数是动态确定的(在运行时)。也就是说,成员函数(在运行时)被动态的选择。该选择基于对象的类型,而不是指向该对象的指针/引用的类型。这被称为“动态绑定”。
纯虚函数(virtual ReturnType Function()= 0)是一个抽象类,是不能被实例化的,它用来规范派生类的行为,实际上也就是所谓的“接口”。
2012-9-26阅读2798 评论0
构造函数不能声明为虚函数,析构函数可以声明为虚函数,而且有时是必须声明为虚函数。
不建议在构造函数和析构函数里面调用虚函数。
构造函数不能声明为虚函数的原因是:
1 构造一个对象的时候,必须知道对象的实际类型,而虚函数行为是在运行期间确定实际类型的。而在构造一个对象时,由于对象还未构造成功。编译器无法知道对象 的实际类型,是该类本身,还是该类的一个派生类,或是更深层次的派生类。无法确定。。。
2 虚函数的执行依赖于虚函数表。而虚函数表在构造函数中进行初始化工作,即初始化vptr,让他指向正确的虚函数表。而在构造对象期间,虚函数表还没有被初 始化,将无法进行。
虚函数的意思就是开启动态绑定,程序会根据对象的动态类型来选择要调用的方法。然而在构造函数运行的时候,这个对象的动态类型还不完整,没有办法确定它到底是什么类型,故构造函数不能动态绑定。(动态绑定是根据对象的动态类型而不是函数名,在调用构造函数之前,这个对象根本就不存在,它怎么动态绑定?)
编译器在调用基类的构造函数的时候并不知道你要构造的是一个基类的对象还是一个派生类的对象。
析构函数设为虚函数的作用:
解释:在类的继承中,如果有基类指针指向派生类,那么用基类指针delete时,如果不定义成虚函数,派生类中派生的那部分无法析构。