多态是一种事物的多种变现形态,不同的对象去完成一件事时会产生不一样的状态。
实现静态多态的方法之一函数重载指的是在同一个作用域内两个函数的名字相同,但是参数列表必须不同,就构成了函数重载。如下图:
而动态多态必须对函数进行重写(虚函数),并且调用函数的对象必须是指针或引用。什么是虚函数呢?在public成员函数前加上关键字virtual:,这样就构成了虚函数,而重写指要求在派生类中有一个和基类中完全相同(返回值,函数名,参数列表)的虚函数,并且为了规范两个函数都需要加上virtual关键字。
两者的不同在于静态多态是编译器在编译期间完成的,编译器会对形成重载的函数进行不同的命名,会根据传参的不同选择调用哪个函数。而动态多态是在程序运行时根据基类的引用(指针)指向的对象来选择哪个虚函数。
还要介绍的就是纯虚函数,形如称为纯虚函数,有纯虚函数的类称为抽象类(接口类),其不能实例化对象,只有在子类中对其进行重写,子类才可实例化出对象。纯虚函数的目的就是在基类中为子类提供了一个接口,以便子类实现。
另外用final修饰的函数不能被派生类重写,重写编译器会报错。
多态的原理:
首先来看一下,下面的sz为什么是8呢?而当成员方法Test1( )中的虚函数取消掉,sz又变为了4
以下就来看一下,其中有些什么:除了成员变量_b外,还有一个void**类型的_vftr指针,我们将这个指针叫做虚函数表指针,其指向虚函数表,虚函数表中存放是虚函数的地址。
虚函数就是用来重写的,那么下面来看一下在派生类中的虚表是什么样子的呢?
- 我们可以看到基类对象b和子类对象d的_vfptr是不全一样的,因为Fun1()完成了重写,所以d的_vfptr中存放的就是Derrive::Fun1(),而Fun2没有在子类中重写,存放的就是Base::Fun2()。
- 我们在实现多态的时候,子类对象就会在其_vfptr中看存放的是否是被重写过的函数,再决定其调用形式
面向过程编程:
优点:面向过程编程比面向对象编程效率较高,因为省去了对象的实例化,开销较小,常用的Linux就是面向过程编程,(一个程序由若干个函数构成)。
缺点:难维护、难复用、难扩展
面向对象编程:
什么是对象:用类实例化出来的就是对象,类中有成员函数和成员变量
优点:易维护、易复用、易扩展,因为有封装、继承、多态的特性,数据被隐藏起来,外界函数访问不到
缺点:性能较低一点
多态的好处:提高了代码的维护性和可扩展性