跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++

C++ 多态的实现原理

C++ 多态的概念、实现条件及注意事项。多态指不同对象执行同一行为产生不同结果,需满足基类指针或引用调用虚函数且子类重写虚函数。析构函数建议设为 virtual 以防止内存泄漏。C++11 引入 override 和 final 关键字辅助检查重写及限制继承。多态针对成员函数,派生类继承接口使用权而非实现。

RedisGeek发布于 2026/3/27更新于 2026/9/1268 浏览

1. 多态

1.1 什么是多态

不同的对象(派生类和基类)执行同一个行为或事件产生的结果是不一样的,即多种状态。

同一个接口,不同的实现;使用不同的派生对象来调用同一个接口会产生不同的状态。且函数接口继承于父类,父类也是可以调用的。

例如:Person 为人,Student 继承了 Person 的派生类,二者均调用一个函数,产生了多种状态。这种情况是如何实现的呢?

1.2 构成多态的条件

通过父类指针或者引用调用虚函数。调用的函数必须是虚函数,且子类对虚函数完成重写。

多态调用与普通调用的区别:

  • 多态调用:被调函数看指向的对象类型。
  • 普通调用:看当前对象的类型。
虚函数

在成员函数前面加上关键字 virtual,并且基类的成员函数和派生类的成员函数的返回值、函数名字以及参数列表(类型、顺序、数量)相同。参数列表相同不包含形参的名字。

虚函数示例

特例

派生类的函数可以不加 virtual,也可以实现虚函数(建议在使用的时候加上,好辨认)。

**协变:**虚函数的返回值可以是父类和子类的引用或者指针,当然自身的父子引用以及其他父子类的引用和指针均可以,父类的引用必须是父类,子类的引用必须是子类。(完全没有必要)

为什么派生类中的函数可以不加 virtual?因为在基类中的函数已经加入 virtual,表明此函数就是虚函数,派生类的继承继承这个函数的性质,在不加 virtual 的时候也是虚函数。

重写是对函数体的重新构建,其他的保持三同,重写还叫做覆盖。

重写(覆盖)与重定义(隐藏)

重写(覆盖)

复用基类虚函数的函数签名和返回值,提供函数更加具体的实现。在编译层面上是通过虚函数表关联的,被视为用同一个函数的不同形态,同一接口的不同行为。在派生类中的函数名字和基类相同的成员函数,不是重写就是重定义。

注:函数标签就是函数名、参数列表和成员函数的 const 限定符。

重定义(隐藏)

本质:派生类中只要存在与基类同名的函数,就会屏蔽基类中所有同名函数。

总结:

  • 重写是'同一个函数的不同实现'(非新函数),依赖虚函数实现多态;
  • 重定义是'同名的不同函数'(新函数),仅存在名称巧合,无多态支持。

1.3 析构函数的多态(重点)

C++ 的类中将析构函数的函数名统一处理为 destructor,为了让析构函数也构成多态。

析构函数多态

但是特殊情况会造成内存泄漏。

内存泄漏风险

由于是指针或者引用调用,在这里实现多态,便可以实现正确的销毁。

正确销毁

总结: 为了构成多态,析构函数的名字统一为 destructor()。子类不加 virtual 也算是析构函数的特权了,但基类的析构函数建议直接加入 virtual。

1.4 C++11 的关键字 override 和 final

final:不让函数重写、不让类被继承。final 表示类为最终的类,不可被继承。

final 限制继承

final 限制重写

override:帮助派生类检测函数重写是否正确,没有重写则报错。

override 检查

将 BuyTicket() 删除末尾的 t,然后就不是函数重写,override 检测还是是否符合三同。

设计不想被继承的类
  1. 私有成员函数在基类中是不可见的,就是不可以使用,使用就会报错的。
  2. 派生类的构造函数必须调用基类构造函数。

将父类的构造函数放入私有中:

class A {
public:
    static A CreatObj() { return A(); }
    int a = 1;
private:
    A() {}
};
class B : public A {
public:
private:
};

将父类的析构函数放入私有中:

class A {
public:
    static A* CreatObj() { return new A(); }
    static void destroyObj(A* obj) { delete obj; }
    int a = 1;
private:
    A() {}
    ~A() {}
};
class B : public A {
public:
private:
};
A* obj = A::CreatObj(); // 创建对象
A::destroyObj(obj);

注意:仅设析构私有可阻止继承,但基类自身的对象无法正常销毁(栈对象无法创建、堆对象无法 delete),因此实际中很少单独这么用,就是老老实实用私有构造函数防止继承吧。

1.5 总结

多态针对的是成员函数(非静态,引用指针调用)虚函数的继承,派生类继承的是接口的使用权,目的是为了重写。实现继承(普通的继承)派生类继承了基类函数,可以使用函数,继承的是函数的实现。

目录

  1. 1. 多态
  2. 1.1 什么是多态
  3. 1.2 构成多态的条件
  4. 虚函数
  5. 特例
  6. 重写(覆盖)与重定义(隐藏)
  7. 1.3 析构函数的多态(重点)
  8. 1.4 C++11 的关键字 override 和 final
  9. 设计不想被继承的类
  10. 1.5 总结

更多推荐文章

查看全部
  • HarmonyOS Next DevEco Studio 构建任务指南
  • EasyOCR Python 开源 OCR 工具使用指南
  • ComfyUI 深度解析:高性能 AI 绘画工作流实践
  • RocketMQ 5.1.4 部署、Docker Dashboard 可视化及 JDK 21 安装指南
  • VS Code 中 GitHub Copilot 高效使用指南:安装与配置
  • 基于开源鸿蒙 OpenHarmony 的智能家居综合应用系统
  • 前端国际化最佳实践
  • RAG 系统链路解析与 Document Loaders 多案例实战
  • Python 解决 ENVIRONMENT_NOT_WRITABLE_ERROR 错误指南
  • 智谱发布 GLM-4-Plus 基座大模型及全模型家族
  • WebGL 基础教程:矩阵变换原理与 3D 动画实战
  • ROS2 slam_toolbox 激光雷达建图配置指南
  • Java 9 至 Java 25:语言演进与技术革新全解析
  • cargo-asm 插件开发指南:为 Rust 项目贡献新功能
  • 校园社团活动管理平台设计:基于 SpringBoot 与 Vue 的实现
  • 高性能计算 FPGA 开发:Quartus Prime 18.0 安装配置指南
  • PyMobileDevice3 Python 控制 iOS 设备教程
  • Gemini 图片无损去水印:基于数学算法的纯前端方案
  • OpenClaw 框架 30+ 真实场景实战拆解
  • Stable Diffusion 3.5 FP8 本地部署与实战指南

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online