一、基本概念
同一操作作用于不同的对象,产生不同的执行结果
👉 就像「按F1键」:在Word弹出帮助文档,在PS弹出画笔设置,同一个按键触发不同功能
(1)多态类型
类型 | 实现方式 | 绑定时机 |
---|---|---|
静态多态 | 函数重载、运算符重载 | 编译时绑定 |
动态多态 | 虚函数+继承体系 | 运行时绑定 |
(2)动态多态三要素
多态满足条件
- 有继承关系
- 子类重写父类中的虚函数
多态使用条件
- 父类指针或引用指向子类对象
重写:函数返回值类型 函数名 参数列表 完全一致称为重写 (缺一不可)
cpp
class 父类名 {
public:
virtual 返回类型 函数名(参数列表) {
// 函数体
}
};
(3)示例代码
cpp
// 父类
class Animal {
public:
virtual void speak() { // 1. 虚函数声明
cout << "动物发声" << endl;
}
};
// 子类
class Cat : public Animal { // 1. 继承关系
public:
void speak() override { // 2. 重写虚函数
cout << "喵喵" << endl;
}
};
// 多态调用
void doSpeak(Animal& animal) { // 3. 父类引用接收子类对象
animal.speak(); // 运行时决定调用哪个实现
}
void doSpeak(Animal *animal) {// 4.用指针接收子类对象
animal->speak();
}
void test() {
Cat cat;
doSpeak(cat); // 输出:喵喵
}
(4)重要特性
函数重写严格一致:(此处是函数内参数不一致)
cpp
// 错误示例:参数不同
class Animal { virtual void func(int) };
class Cat : public Animal { void func() }; // 不会触发多态
二、多态原理
当子类重写父类的虚函数,子类中的虚函数表内部,会替换成 子类的虚函数地址
例
cpp
class Animal
{
public:
//虚函数
virtual void speak()
{
cout << "动物在说话" << endl;
}
};
cpp
//猫类
class Cat : public Animal
{
public:
//重写 函数返回值类型 函数名 参数列表 完全相同
virtual void speak()
{
cout << "小猫在说话" << endl;
}
};
原理概况

当父类的指针或者引用指向子类对象时候,发生多态
cpp
Animal & animal = cat;
animal.speak();
cpp
vfptr - 虚函数(表)指针
v - virtual
f - function
ptr - pointer
vtable - 虚函数表
v - virtual
f - function
table - table
三、纯虚函数和抽象类
在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容
因此可以将虚函数改为纯虚函数,当类中有了纯虚函数,这个类也称为抽象类
纯虚函数语法:virtual 返回值类型 函数名(参数列表)= 0 ;
virtual void func() = 0;
抽象类特点:
1、无法实例化对象
cpp若Base是抽象类,则下面两行报错 Base b; new Base;
2、子类必须重写抽象类中的纯虚函数,否则也属于抽象类
++写纯虚函数意义就是想让子类重写一遍纯虚函数++
四、虚析构与纯虚析构
1.核心问题
内存泄漏场景
cpp
class Animal {
public:
~Animal() { // ❌ 普通析构
cout << "Animal析构" << endl;
}
};
class Cat : public Animal {
public:
~Cat() {
cout << "Cat析构" << endl;
delete[] m_data; // 堆内存资源
}
private:
int* m_data = new int[100];
};
void test() {
Animal* pet = new Cat();
pet->speak();
delete pet; // 仅调用Animal析构 → 内存泄漏!
}
执行结果:
cpp
Animal析构
(Cat析构未被调用 → m_data内存泄漏)
2.解决方案对比
方案类型 | 语法示例 | 类性质 | 实现要求 | 使用场景 |
---|---|---|---|---|
虚析构 | virtual ~Animal() {} |
普通类 | 必须实现 | 需要实例化基类对象 |
纯虚析构 | virtual ~Animal() = 0; |
抽象类 | 必须单独实现 | 强制子类实现特定行为 |
3.具体实现
1. 虚析构函数
cpp
class Animal {
public:
virtual ~Animal() { // ✅ 虚析构声明
cout << "Animal虚析构" << endl;
}
};
// 正确执行结果:
// Cat析构
// Animal虚析构
2. 纯虚析构函数
cpp
class Animal {
public:
virtual ~Animal() = 0; // 纯虚析构声明
};
// 必须单独实现
Animal::~Animal() { // ✅ 纯虚析构实现
cout << "Animal纯虚析构" << endl;
}
特性:
- 使类成为抽象类(无法实例化)
- 子类必须实现析构函数
cpp
class Cat : public Animal {
public:
~Cat() override { // 必须实现
cout << "Cat析构" << endl;
}
};