C++多态和虚函数

41 阅读2分钟

“多态(polymorphism)”指的是同一名字的事物可以完成不同的功能。

多态可以分为编译时的多态和运行时的多态。

编译时的多态(静态多态):主要是指函数的重载(包括运算符的重载)、对重载函数的调用,在编译时就能根据实参确定函数地址,然后确定调用哪个函数。

运行时的多态(动态多态):和继承、虚函数等概念有关,运行阶段确定函数地址。

构成动态多态的满足条件:

  • 有继承关系
  • 子类重写父类的虚函数
  • 存在父类的指针,通过该指针调用虚函数。

动态多态使用:父类的指针或引用指向子类对象

虚函数

虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。

虚函数是根据指针的指向来调用的,指针指向哪个类的对象就调用哪个类的虚函数。

纯虚函数

将虚函数声明为纯虚函数,语法格式为:

virtual 返回值类型 函数名 (函数参数) = 0;

纯虚函数没有函数体,只有函数声明,在虚函数声明的结尾加上=0,表明此函数为纯虚函数。

包含纯虚函数的类称为抽象类(Abstract Class)。之所以说它抽象,是因为它无法实例化,也就是无法创建对象。原因很明显,纯虚函数没有函数体,不是完整的函数,无法调用,也无法为其分配内存空间。

抽象基类中除了包含纯虚函数外,还可以包含其它的成员函数(虚函数或普通函数)和成员变量。

只有类中的虚函数才能被声明为纯虚函数,普通成员函数和顶层函数均不能声明为纯虚函数。

通常是基类作为抽象类,让派生类去实现纯虚函数。派生类必须实现纯虚函数才能被实例化

虚析构和纯虚析构

多态使用时,如果子类有属性开辟到堆区,那么父类指针在释放时无法调用子类的析构函数

解决方式:将父类的析构函数改为虚析构和纯虚析构

虚析构和纯虚析构异同:

同:

  • 可以解决父类指针释放子类对象
  • 都需要有具体的函数实现

异:

  • 如果是纯虚构,该类属于抽象类,无法实例化对象

语法:

//虚析构
virtual ~类名(){}
//纯虚析构
virtual ~类名(){} = 0;