基本概念
- 目的:提升程序可扩充性
- 在类定义里的函数声明前加上virtual即是虚函数,在类外写函数体时不用加
- 构造函数和静态成员函数不能是虚函数
- 表现形式
- 派生类对象赋值给基类指针,则当基类指针调用基类和派生类同名虚函数时,实际执行的函数是根据指针指向的对象
- 派生类对象赋值给基类引用,同上。
- 通过基类指针或引用调用虚函数,程序编译时不确定调用的基类或是派生类,直到运行时才确定——动态联编
用法
- 用基类指针数组存放指向各种派生类对象的指针,然后遍历数组,实现对不同派生类的对象的操作,是一种比较常见的做法
- 派生类和基类中虚函数同名同参数表的函数,不加virtual也自动成为虚函数
- 类中非构造函数、非析构函数内部调用虚函数时是多态(因为函数内包含的
this
指针); - 类中的构造函数、析构函数内部调用虚函数时不是多态,在编译时已确定(因为基类构造时,派生类的变量还未初始化;基类析构时,派生类已析构,若为多态,则可能出错)
多态的实现原理
- 在每个包含虚函数的类及其派生类的对象存储空间首部,都包含着一个指向虚函数表的指针。调用虚函数时,程序会通过该指针运行指向的虚函数。
- 缺点:增加时间和空间的损耗
虚析构函数
- 当类中存在虚函数或需要用基类指针或引用调用派生类时,应在基类虚构函数前加上virtual,派生类的析构函数不需要加virtual
- 否则,当用基类指针删除派生类对象时,只会调用基类析构函数,而不会调用派生类析构函数,析构不充分
纯虚函数和抽象类
-
定义:没有函数体的虚函数称为纯虚函数,包含纯虚函数的类为抽象类
virtual void Func()=0;
-
抽象类不能直接创建相应的对象,只能用于派生新类使用。抽象类指针可以指向派生出的对象
-
抽象类成员函数内部可以调用纯虚函数,但其构造函数&析构函数内不能直接调用[1]
-
派生类当且仅当实现基类中所有纯虚函数后,才不是抽象类
因为构造、析构函数内不是多态,所以不能直接调用纯虚函数 ↩︎