C++多态编程:从原理到实战

一、多态核心概念

1. 什么是多态?

同一个行为,不同对象有不同实现 。父类引用 / 指针 指向 子类对象,调用函数时,执行子类重写的版本

2. 多态价值

  • 降低耦合,代码高扩展
  • 父类统一接口,子类自由实现
  • 新增子类无需修改原有业务代码,符合开闭原则

3. 实现多态的三大必要条件

  1. 必须存在继承关系
  2. 父类函数必须加 virtual 虚函数
  3. 父类指针 / 引用 指向 子类对象(向上转型)

二、静态绑定 & 动态绑定

  1. **静态绑定(早绑定)**编译阶段确定函数地址,普通成员函数默认都是静态绑定。
  2. 动态绑定(晚绑定) 运行阶段根据真实对象类型 匹配函数,虚函数触发动态绑定 → 产生多态。

三、虚函数 virtual 基础语法

父类声明虚函数,子类重写该函数,即可构成多态。

复制代码
virtual 返回值 函数名(参数);

完整多态演示

复制代码
#include <iostream>
using namespace std;

// 父类
class Animal
{
public:
    // 虚函数
    virtual void speak()
    {
        cout << "动物发出声音" << endl;
    }
};

// 子类Dog
class Dog : public Animal
{
public:
    // 重写虚函数
    void speak()
    {
        cout << "小狗汪汪叫" << endl;
    }
};

// 子类Cat
class Cat : public Animal
{
public:
    void speak()
    {
        cout << "小猫喵喵叫" << endl;
    }
};

向上转型 + 多态调用

复制代码
// 父类指针指向子类对象
void doSpeak(Animal *a)
{
    a->speak(); 
}

int main()
{
    Dog d;
    Cat c;

    doSpeak(&d);
    doSpeak(&c);

    return 0;
}

输出:

复制代码
小狗汪汪叫
小猫喵喵叫

同一接口 speak(),不同子类不同表现,多态生效


四、函数重写(override)规则

  1. 子类函数与父类函数名、参数、返回值完全一致

  2. 父类必须是 virtual 虚函数

  3. 子类可加 override 关键字显式标记,编译器校验

    void speak() override;

重写 / 重载 / 隐藏 三者区分

  1. 重载:同类中,同名不同参,编译绑定
  2. 隐藏:继承中,子类同名函数屏蔽父类,无 virtual
  3. 重写:继承 + 虚函数,运行绑定,实现多态

五、向上转型 & 向下转型

1. 向上转型(多态核心,常用)

子类对象 赋值给 父类指针 / 引用语法安全、自动转换,多态全部依赖它。

复制代码
Animal* a = new Dog;

2. 向下转型(不安全,少用)

父类指针强制转回子类,需要手动强转,容易越界。

复制代码
Dog* d = (Dog*)a;

六、虚析构函数(工程必踩坑)

当父类指针指向子类堆对象,delete 释放时:

  • 若析构非虚:只调用父类析构,子类资源不释放 → 内存泄漏
  • 父类加 virtual 虚析构:先子类析构,再父类析构

标准写法

复制代码
class Animal
{
public:
    virtual ~Animal(){}
};

只要类中有虚函数,必须把析构写成虚析构。


七、纯虚函数 & 抽象类

1. 纯虚函数语法

复制代码
virtual void func() = 0;

2. 抽象类

包含至少一个纯虚函数的类,特点:

  • 无法实例化对象
  • 只做父类,定义统一接口
  • 子类必须重写所有纯虚函数,否则子类也是抽象类

示例

复制代码
class Shape
{
public:
    // 纯虚函数
    virtual void getArea() = 0;
};

// 圆形子类必须实现纯虚函数
class Circle : public Shape
{
public:
    void getArea() override
    {
        cout << "计算圆形面积" << endl;
    }
};

八、多态底层简单理解

  • 含有虚函数的类,内部会生成虚函数表 (vtable)
  • 对象自带虚表指针 (vptr)
  • 运行时通过虚表指针,找到真实子类的函数地址
  • 实现运行时动态绑定

九、高频易错点

  1. 忘了写 virtual,只会触发隐藏,没有多态
  2. 重写时参数 / 返回值不一致,不构成重写
  3. 父类指针 delete 子类对象,未写虚析构 → 内存泄漏
  4. 抽象类直接实例化对象,编译报错
  5. 混淆重载、重写、隐藏三种概念

十、今日核心总结

  1. 多态三要素:继承 + 虚函数 + 向上转型
  2. virtual 开启动态绑定,运行时决定调用哪个函数
  3. 子类重写虚函数,实现个性化逻辑
  4. 有虚函数必须搭配虚析构
  5. 纯虚函数 → 抽象类,用于定义标准接口
相关推荐
炸膛坦客8 小时前
单片机/C/C++八股:(二十六)IIC 专题(I²C)---- 上集
c语言·c++·单片机
旖-旎8 小时前
LeetCode 518:零钱兑换||(完全背包)—— 题解
c++·算法·leetcode·动态规划·背包问题
灯澜忆梦8 小时前
GO_并发编程---定时器
开发语言·后端·golang
-银雾鸢尾-8 小时前
C#中的StringBuilder相关方法
开发语言·c#
Henry Zhu1238 小时前
C++中的特殊成员函数与智能指针
c++
-银雾鸢尾-9 小时前
C#中结构体与类的区别;抽象类与接口的区别
开发语言·c#
大模型码小白10 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
_wyt00111 小时前
多重背包问题详解
c++·背包dp
段一凡-华北理工大学11 小时前
向量数据库实战:选型、调优与落地~系列文章12:文本分块策略实战:chunk_size 怎么选?重叠多少?
开发语言·数据库·后端·oracle·rust·工业智能体·高炉智能化
Ljwuhe12 小时前
C++——多态
开发语言·c++