谈谈你对虚函数的理解
//什么是多态
//实现多态性的方式
//虚函数是怎么实现的
//虚函数的说明
//虚析构函数
//构造函数和析构函数的调用顺序
//纯虚函数与抽象类
//为什么要引用抽象基类和纯虚函数
//虚函数与纯虚函数的区别
什么是多态
多态性是指发出的消息被不同的对象接收时会产生完全不同的行为
(同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果)
实现多态性的方式
<1>运算符重载和函数重载
静态关联:关联工作在编译、链接阶段完成,在此期间,系统就可以根据函数的参数类型和参数个数决定调用哪个同名函数。
静态关联的优缺点:程序执行效率高,但对程序员水平要求较高
<2>虚函数和纯虚函数
动态关联:关联工作在程序运行阶段完成。
动态关联的优缺点:提供更好的编程灵活性、问题抽象性和程序的易维护性,但是函数调用速度慢
虚函数是怎么实现的(通过虚函数表实现)
<1>定义:
virtual 函数类型 函数名(参数表)
{
函数体;
}
<2>如何利用虚函数实现运行时的多态
记住,通过对象调用虚函数不会出现多态(通过指针或者引用才会有多态性)
在构造函数里面调用虚函数不会出现多态,指定命名域调用不会出现多态
虚函数的说明
<1>派生类应该从它的基类公有派生。一个虚函数无论被公有继承多少次,它仍然保持虚函数的特性
<2>必须首先在基类中定义虚函数。应该在需要具有动态多态性的最高层内首先声明虚函数
<3>在派生类中对基类声明的虚函数进行重定义时,关键字virtual可写可不写,但在容易引起混乱的情况下,建议加上virtual
<4>只有通过基类指针或者基类引用访问虚函数时才能获得运行时的多态性
<5>虚函数必须是其所在类的成员函数,而不能是友元函数,更不能是静态成员函数,因为虚函数调用要靠特定对象来**对应的函数
<6>内联函数不能使虚函数,因为内联函数时不能在运行时动态确定其位置的
虚析构函数(为什么我们不提虚构造函数呢?)
virtual ~类名(){}
只有析构函数可以被声明为虚函数,构造函数不能声明为虚函数!!!
虚函数是根据不同类型的对象产生不同的动作,构造函数是在对象生成之前调用的,如果对象还没有产生,那么虚构造函数也就没什么意义
如果一个类的析构函数时虚函数,那么由它派生而来的所有派生类的析构函数,不管是否用virtual进行说明,也都是虚析构函数。保证使用时基类类型的指针能够调用适当的析构函数针对不同的对象进行清理工作
构造函数和析构函数的调用顺序(包含多重继承、类中包含对象成员)
构造函数顺序:首先调用基类的构造函数(先调用哪个基类 与 派生类继承基类的顺序一致)
(若为菱形结构,则基虚类构造函数只被调用一次)
其次调用类的对象成员的构造函数(先调用哪个对象成员的构造函数 与 对象成员的定义顺序一致)
最后调用派生类的构造函数
析构函数的调用顺序与构造函数相反
纯虚函数与抽象类
包含纯虚函数的类被称为抽象类
class <类名>
{
virtual <类名> <函数名> (<参数表>) = 0;
}
纯虚函数的作用是在基类中为派生类保留一个函数的名字,以便派生类根据需要对它进行定义。
为什么要引用抽象基类和纯虚函数
<1>为了方便使用多态性
<2>在很多情况下,基类本身生成对象是不合理的。例如:动物作为一个基类可以派生出老虎、狮子等子类,但动物本身生成对象明显不合常理。抽象基类不能够被实例化,它定义的纯虚函数相当于接口,能把派生类的共同行为提取出来。
虚函数与纯虚函数的区别
<1>虚函数是实现的,哪怕是空实现;纯虚函数只是一个接口,是函数声明,需要子类去实现
<2>虚函数在子类中也可以不修改;但纯虚函数必须在子类中实现
<3>虚函数的类用于“实作继承”,也就是说继承接口的同时也继承了父类的实现,当然也可以完成自己的实现;纯虚函数的类用于“介面继承”,即纯虚函数关注的是接口统一性,实现由子类完成
<4>带纯虚函数的类叫虚基类(抽象类),这种类不能直接实例化对象,只有被继承,并实现其纯虚函数后,才能使用
上一篇: embed 参数
下一篇: 使用libmp3lame库编码mp3