C++多态性
- 什么是多态性
(1).我们一般可以这么描述多态性:向不同的对象发送同一个消息,不同对象在接受是会产生出不同的行为。可以提高代码的可拓展性。
(2).在C++中,多态性表现形式之一是:具有不同功能的函数可以用同一个函数名,这样可以实现用一共函数名调用不同内容的函数。
(3).多态性可以分为俩类静态多态性<通过函数重载实现,好处:函数调用速度快,效率高,但缺乏灵活性,在程序运行前就已决定了执行的函数和方法>(编译时的动态性) 和 动态多态性<通过虚函数实现,好处:不在编译时确定调用哪个函数,而是在程序运行过程重才动态地确定操作所针对的对象>(运行时的多态性)
- 虚函数的作用
我们可以不需要在每个类中的相同的成员函数都单独的写出它的指向,比如Circle::area(),我们可以在程序重不是通过不同的对象名去调用不同派生层次中的同名函数,而是通过指针调用他们。(虚函数的作用是允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的同名函数
在不用虚函数的情况下,以下代码状态是:
我们发现这里就出现了基类和派生类类型转换,我们没法完全输出派生类所具有的所有数据类型,只能输出基类的输出类型。
倘若在display函数加上虚函数的标识virtual,又会是怎么样呢。
我们发现,派生类自己的数据就能够输出出来了,这就是虚函数存在的意义。
我们总结以下虚函数的使用方法:
(1).在基类中用virtual声明成员函数为虚函数。在类外定义虚函数时,不必再函数名前面再加virtual。
(2).在派生类中重新定义此函数,函数名,函数类型,函数参数个数和类型必须和基类的虚函数相同,根据派生类的需要重新定义函数体。当一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数。因此在派生类重新声明该虚函数时,可以加上virtual,也可以不加,但习惯上一般在每一层声明该函数时都加virtual,使程序更加清晰。
(3).定义一个指向基类对象的指针变量,并使它指向同一类族中需要调用该函数的对象。
(4).通过该指针变量调用此虚函数,此时调用的就是指针变量指向的对象的同名函数。
那么我有又在什么情况下应当声明虚函数
(1).只能用virtual声明类的成员函数,把它作为虚函数,而不能将类外的普通函数声明为虚函数。因为虚函数的作用时允许在派生类中对基类的虚函数重新定义。显然,它只能用用于类的继承层次构造中。
(2).一个成员函数被声明为虚函数后,在同一类族中的类就不能再定义一共非virtual的但与该虚函数具有相同的参数和函数返回值类型的同名函数。
那么我们又要根据声明把一个成员函数声明为虚函数呢
(1).首先看成员函数所在的类是否会作为基类。然后看成员函数在类的继承后有无可能被更改功能,如果希望更改其功能的,一般应该将它声明为虚函数。
(2).如果成员函数在类被继承后功能无须修改,或派生类用不到该函数,则不要把它声明为虚函数。不要仅仅考虑到要作为基类而把类中的所有成员函数都声明为虚函数。
(3).应考虑对成员函数的调用时通过对象名还是通过基类指针或引用去访问,如果通过基类指针或引用去访问的,则应当声明为虚函数。
(4).有时,在定义虚函数时,并不定义其函数体,即函数体是空的。它的作用只是定义了一个虚函数名,具体功能留给派生类去添加。
那么我们就要讲到虚函数的原理,我们在使用虚函数的时候,系统要有一定的空间开销。当一个类带有虚函数时,编译会为该类构造一个虚函数表,它是一个指针数组,存放每个虚函数的入口地址。
- 纯虚函数与抽象类
首先,我们先知道它的定义方式
virtual 函数类型 函数名(参数列表)=0;
注意:(1).纯虚函数没有函数体;(2).最后面的“=0“并不表示函数返回值为0,它只是起形式上的作用,告诉编译系统”这是纯虚函数“;(3).这是一个声明语句,最后应该有分号。
纯虚函数的作用:是在基类中为其派生类保留一个函数的名字,以便派生类根据需要对它进行定义。如果在基类中没有保留函数名字,则无法实现多态性。
如果在一个类中声明了纯虚函数,而在其派生类中没有对该函数定义,则该虚函数在派生类中仍然为纯虚函数。
何为抽象类,简单来说只要包含纯虚函数的类都是抽象类。
作用:作为一个类族的共同的基类,或者说,为一个类族提供一个公共接口。