一、核心定义

多态:同一个接口,不同对象实现不同行为,分为静态多态、动态多态。

1. 静态多态(编译期)

编译阶段就确定调用哪个函数

  • 函数重载:同名函数,参数列表不同
void func(int a);
void func(double a);
  • 运算符重载:+== 等运算符自定义行为

2. 动态多态(运行时)

运行时才确定函数,满足3个条件:

  1. 存在继承关系(子类公有继承父类)
  2. 父类函数加 virtual 虚函数
  3. 子类重写(override)同名同参虚函数
  4. 使用父类指针/引用指向子类对象

示例代码

#include <iostream>
using namespace std;

// 父类
class Base {
public:
    virtual void show() { // 虚函数
        cout << "父类" << endl;
    }
};

// 子类
class Son : public Base {
public:
    void show() override { // 重写虚函数
        cout << "子类" << endl;
    }
};

int main() {
    Base* p = new Son(); // 父类指针指向子类
    p->show(); // 运行多态:输出 子类
    delete p;
    return 0;
}

二、关键概念

  1. 虚函数 virtual
    父类不加virtual:不会触发多态,永远调用父类函数。
  2. 重写 override
    子类函数必须和父类虚函数函数名、参数、返回值完全一致,override关键字用于检查重写是否合法。
  3. 虚析构函数 virtual ~Base()
    父类析构不加virtual时,父类指针释放子类对象,只会调用父类析构,子类析构不执行,内存泄漏
virtual ~Base(){} // 规范写法
  1. 纯虚函数(抽象类)
virtual void func() = 0;
  • 包含纯虚函数的类 = 抽象类,不能实例化创建对象
  • 子类必须全部重写纯虚函数,否则子类仍是抽象类

三、静态 vs 动态多态对比

类型 时机 实现方式
静态多态 编译期 重载、模板
动态多态 运行期 继承+虚函数+父类指针/引用

四、底层原理

类存在虚函数时,会生成虚函数表 vtable,对象内部自带虚表指针 vptr;运行时通过vptr查找对应子类函数,实现多态。

更多推荐