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. 纯虚函数 → 抽象类,用于定义标准接口
相关推荐
今天又在写代码1 小时前
并发问题解决
java·开发语言·数据库
聆风吟º1 小时前
【C标准库】深入理解C语言strcat函数:字符串拼接的利器
c语言·开发语言·strcat·库函数
6Hzlia1 小时前
【Hot 100 刷题计划】 LeetCode 24. 两两交换链表中的节点 | C++ 精准指针舞步
c++·leetcode·链表
带娃的IT创业者1 小时前
深度解析:从零构建高性能 LLM API 中转网关与成本优化实战
开发语言·gpt·llm·php·高性能·成本优化·api网关
TechWayfarer1 小时前
IP归属地运营商能解决什么问题?风控/增长/数据平台落地实践(附API代码)
开发语言·网络·python·网络协议·tcp/ip
Alice-YUE2 小时前
【JS高频八股】什么是闭包?
开发语言·javascript·笔记·学习
微学AI2 小时前
Claude-Code-python 前端改造项目工作流程详解
开发语言·前端·python
汉克老师2 小时前
GESP2025年6月认证C++五级( 第一部分选择题(9-15))
c++·贪心算法·分治算法·二分算法·gesp5级·gesp五级·高精度除法