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. 纯虚函数 → 抽象类,用于定义标准接口
相关推荐
用户8055336980314 小时前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
BadBadBad__AK1 天前
线段树维护区间 k 次方和
c++·数学·算法·stl
卷无止境2 天前
Eigen 库如何借助 OpenMP 加速计算
c++·后端
卷无止境2 天前
OpenMPI、MPICH 与 OpenMP:关系、核心概念与架构全解
c++·后端
郝学胜_神的一滴3 天前
CMake 30:循环语法全解|foreach_while双循环精讲、迭代技巧与实战避坑指南
c++·cmake
卷无止境5 天前
C++ 的Eigen 库全解析
c++
卷无止境5 天前
现代 C++特性大盘点:一门脱胎换骨的老语言
c++·后端
郝学胜_神的一滴5 天前
CMake 27:缓存变量的特性、语法、类型与实操全解
c++·cmake
博客18007 天前
酷宝的使用方法,超好用的免费界面库,C++、MFC可用
c++·mfc·界面库·库来帮·酷宝
郝学胜_神的一滴7 天前
CMake 026:属性体系精讲、四大作用域全解 & 实战代码落地
c++·cmake