C++中的多态:动态多态与静态多态详解

作者:oioihoii日期:2025/11/6

多态是面向对象编程的三大特性之一,C++提供了两种主要的多态形式:动态多态和静态多态。本文将详细解释它们的区别,并通过代码示例进行说明。

什么是多态?

多态(Polymorphism)指同一个接口可以表现出不同的行为。在C++中,这允许我们使用统一的接口来处理不同类型的对象。

动态多态(运行时多态)

动态多态在程序运行时确定调用哪个函数,主要通过虚函数和继承机制实现。

实现机制

  • 使用虚函数(virtual function)
  • 通过继承关系
  • 运行时通过虚函数表(vtable)决定调用哪个函数

代码示例

1#include <iostream>
2using namespace std;
3
4// 基类
5class Animal {
6public:
7    // 虚函数
8    virtual void makeSound() {
9        cout << "Animal makes a sound" << endl;
10    }
11    
12    virtual ~Animal() = default; // 虚析构函数
13};
14
15// 派生类
16class Dog : public Animal {
17public:
18    void makeSound() override {
19        cout << "Dog barks: Woof! Woof!" << endl;
20    }
21};
22
23class Cat : public Animal {
24public:
25    void makeSound() override {
26        cout << "Cat meows: Meow! Meow!" << endl;
27    }
28};
29
30// 使用动态多态
31void animalSound(Animal* animal) {
32    animal->makeSound(); // 运行时决定调用哪个makeSound
33}
34
35int main() {
36    Dog dog;
37    Cat cat;
38    Animal animal;
39    
40    // 通过基类指针调用,表现出多态行为
41    Animal* animals[] = {&animal, &dog, &cat};
42    
43    for (auto* animal : animals) {
44        animalSound(animal);
45    }
46    
47    return 0;
48}
49

输出:

1Animal makes a sound
2Dog barks: Woof! Woof!
3Cat meows: Meow! Meow!
4

动态多态特点

  • 运行时绑定:函数调用在运行时决定
  • 灵活性高:可以在运行时改变行为
  • 性能开销:有虚函数表查找的开销
  • 必须使用指针或引用:通过基类指针或引用调用

静态多态(编译时多态)

静态多态在编译时确定调用哪个函数,主要通过函数重载和模板实现。

1. 函数重载

1#include <iostream>
2using namespace std;
3
4class Calculator {
5public:
6    // 函数重载 - 静态多态
7    int add(int a, int b) {
8        return a + b;
9    }
10    
11    double add(double a, double b) {
12        return a + b;
13    }
14    
15    string add(const string& a, const string& b) {
16        return a + b;
17    }
18};
19
20int main() {
21    Calculator calc;
22    
23    cout << "Int addition: " << calc.add(5, 3) << endl;
24    cout << "Double addition: " << calc.add(5.5, 3.3) << endl;
25    cout << "String addition: " << calc.add("Hello, ", "World!") << endl;
26    
27    return 0;
28}
29

输出:

1Int addition: 8
2Double addition: 8.8
3String addition: Hello, World!
4

2. 模板(泛型编程)

1#include <iostream>
2#include <vector>
3#include <list>
4using namespace std;
5
6// 函数模板 - 静态多态
7template<typename T>
8T multiply(T a, T b) {
9    return a * b;
10}
11
12// 类模板
13template<typename Container>
14void printContainer(const Container& container) {
15    for (const auto& item : container) {
16        cout << item << " ";
17    }
18    cout << endl;
19}
20
21// 特化示例
22template<>
23string multiply<string>(string a, string b) {
24    return "String multiplication not supported";
25}
26
27int main() {
28    // 模板函数使用
29    cout << "Int multiplication: " << multiply(5, 3) << endl;
30    cout << "Double multiplication: " << multiply(5.5, 2.0) << endl;
31    cout << "String multiplication: " << multiply<string>("hello", "world") << endl;
32    
33    // 模板类使用
34    vector<int> vec = {1, 2, 3, 4, 5};
35    list<string> lst = {"apple", "banana", "cherry"};
36    
37    cout << "Vector: ";
38    printContainer(vec);
39    
40    cout << "List: ";
41    printContainer(lst);
42    
43    return 0;
44}
45

输出:

1Int multiplication: 15
2Double multiplication: 11
3String multiplication: String multiplication not supported
4Vector: 1 2 3 4 5 
5List: apple banana cherry 
6

3. CRTP(奇异递归模板模式)

1#include <iostream>
2using namespace std;
3
4// CRTP基类
5template<typename Derived>
6class AnimalBase {
7public:
8    void makeSound() {
9        static_cast<Derived*>(this)->makeSoundImpl();
10    }
11};
12
13// 派生类
14class Dog : public AnimalBase<Dog> {
15public:
16    void makeSoundImpl() {
17        cout << "Dog barks: Woof! Woof!" << endl;
18    }
19};
20
21class Cat : public AnimalBase<Cat> {
22public:
23    void makeSoundImpl() {
24        cout << "Cat meows: Meow! Meow!" << endl;
25    }
26};
27
28// 使用静态多态
29template<typename T>
30void animalSound(AnimalBase<T>& animal) {
31    animal.makeSound(); // 编译时决定调用哪个函数
32}
33
34int main() {
35    Dog dog;
36    Cat cat;
37    
38    animalSound(dog);
39    animalSound(cat);
40    
41    return 0;
42}
43

输出:

1Dog barks: Woof! Woof!
2Cat meows: Meow! Meow!
3

动态多态 vs 静态多态

特性动态多态静态多态
绑定时间运行时编译时
实现机制虚函数、继承模板、函数重载
性能有运行时开销(虚表查找)无运行时开销
灵活性运行时决定行为编译时决定行为
二进制大小较小可能较大(模板实例化)
调试难度相对容易相对困难
使用场景需要运行时动态行为性能要求高,类型已知

实际应用建议

使用动态多态的场景:

  • 需要在运行时决定对象类型
  • 有复杂的继承层次结构
  • 需要插件架构或动态加载
  • 代码可读性和维护性更重要

使用静态多态的场景:

  • 性能是关键因素
  • 类型在编译时已知
  • 需要避免虚函数开销
  • 使用模板元编程

总结

C++中的多态提供了强大的代码复用和灵活性:

  • 动态多态通过虚函数提供运行时灵活性,适合需要动态行为变化的场景
  • 静态多态通过模板和重载提供零开销的抽象,适合性能敏感的场景

在实际开发中,应根据具体需求选择合适的多态方式,有时甚至可以结合使用两者以获得最佳效果。理解这两种多态的区别和适用场景,有助于编写更高效、更灵活的C++代码。


C++中的多态:动态多态与静态多态详解》 是转载文章,点击查看原文


相关推荐


图的寻路算法详解:基于深度优先搜索(DFS)的实现
Seal^_^2025/11/2

图的寻路算法详解:基于深度优先搜索DFS的实现 一、寻路算法概述DFS寻路示例 二、算法核心思想数据结构设计 三、算法实现详解1. 核心数据结构2. 构造函数初始化3. DFS实现4. 路径查询方法 四、完整代码实现五、算法测试与应用测试代码输出结果 六、算法分析与优化时间复杂度分析空间复杂度优化方向 七、DFS寻路与BFS寻路对比八、实际应用场景九、总结 🌺The Begin🌺点点关注,收藏不迷路🌺


高并发压力测试:Llama-2-7b 在昇腾 NPU 的六大场景表现
2501_938774292025/10/30

以下是关于 Llama-2-7b 在昇腾 NPU 上进行高并发压力测试的六大场景表现分析,结合网络公开信息和技术逻辑整理而成: 场景一:文本生成吞吐量测试 在批量文本生成任务中(如问答、摘要),昇腾 NPU 通过异构计算架构优化模型并行度。实测数据显示,当并发请求数从 100 提升至 1000 时,吞吐量增长约 3.8 倍,但单请求响应时间增加 15%-20%,显存占用峰值达 80%。 关键指标: 吞吐量:1200 tokens/s(batch_size=32)延迟:50ms/toke


Swift 官方发布 Android SDK | 肘子的 Swift 周报 #0108
东坡肘子2025/10/28

📮 想持续关注 Swift 技术前沿? 每周一期《肘子的 Swift 周报》,为你精选本周最值得关注的 Swift、SwiftUI 技术文章、开源项目和社区动态。 📬 在 weekly.fatbobman.com 免费订阅 💬 加入 Discord 与中文 Swift 开发者深入交流 📚 访问 fatbobman.com 查看数百篇深度原创教程  一起构建更好的 Swift 应用!🚀 Swift 官方发布 Android SDK 10 月 24 日,Swift Android 工


大模型时代的广告营销变革与实践
京东零售技术2025/10/25

大模型时代的广告营销变革与实践 互联网领域,广告营销是一种核心业态,也是先进技术和研究成果的商业化进程最快的一种渠道。伴随生成式大模型的浪潮汹涌袭来,京东广告结合自身业务特性和电商零售的新业态,推出了自主研发的广告营销商业化场景大模型,并据此带来了一场深刻的技术和业务变革。 在2025年9月25日,京东JDD(京东全球科技探索者)大会的Oxygen 智能零售论坛上,京东广告团队做了题为《大模型时代的广告营销变革与实践》的报告。 核心观点 1. 通用大模型想解决营销领域问题需向垂类模型转型。 “全


【Java】基于 Tabula 的 PDF 合并单元格内容提取
Kida的躺平小屋2025/10/22

坑还是要填的,但是填得是否平整就有待商榷了(狗头保命...)。 本人技术有限,只能帮各位实现的这个地步了。各路大神如果还有更好的实现也可以发出来跟小弟共勉一下哈。 首先需要说一下的是以下提供的代码仅作研究参考使用,各位在使用之前务必自检,因为并不是所有 pdf 的表格格式都适合。 本次实现的难点在于 PDF 是一种视觉格式,而不是语义格式。 它只记录了“在 (x, y) 坐标绘制文本 'ABC'”和“从 (x1, y1) 到 (x2, y2) 绘制一条线”。它根本不“知道”什么是“表格”、“


猿辅导Java面试真实经历与深度总结(二)
360_go_php2025/10/22

​ 在面试中,掌握Java的基础知识和深入的理解是非常重要的。今天,我们来解析几个常见的Java面试问题,包括线程状态、线程池、深拷贝与浅拷贝、线程安全、Lock与Synchronized的区别,以及逃逸分析等话题。 1. 线程状态 Java中,线程有七种状态,它们是由 Thread.State 枚举类定义的。线程的状态随着程序的执行而发生变化,下面是七种状态的描述:​编辑 NEW:线程被创建,但尚未启动。 RUNNABLE:线程可以运行,或者已经正在运行。线程调度器选择合适的线程让它执行


Docker 通信核心:docker.sock 完全指南
做运维的阿瑞2025/10/20

阅读时长: 15min | 难度: 中级 | 作者: 做运维的阿瑞 | 更新时间: 2025-10 文章目录 前言一、Docker 通信原理总览1.1 技术架构解析1.2 核心技术对比 二、核心用法与技巧2.1 容器内访问宿主机 Docker2.2 使用 Docker SDK2.3 直接与 API 交互 三、安全风险与最佳实践Q1: 有多危险?为什么说拿到 `docker.sock` 就等于 `root`?Q2: 如何安全地授权用户使用 Docker?Q3: 有没有比挂


自定义Spring Boot Starter项目并且在其他项目中通过pom引入使用
劝导小子2025/10/19

1、创建starter项目 我电脑只有JDK 8,但是创建项目的时候最低只能选择17,后续创建完后去修改即可 2、项目结构 删除主启动类Application:Starter不需要启动类删除配置文件application.properties:Starter不需要自己的配置文件删除test里面的测试启动类 在resources下创建META-INF文件夹 3、修改JDK 修改成JDK8,如果你有更高的版本请切换 4、配置pom.xml <?xml version="1


RabbitMQ消息传输中Protostuff序列化数据异常的深度解析与解决方案
Mr.45672025/10/18

目录 问题背景 环境配置 使用的依赖 测试对象 初始代码(有问题的版本) 问题分析 1. 初步排查 2. 关键发现 3. RabbitTemplate的默认行为分析 4. SimpleMessageConverter的处理机制 深入理解消息转换 消息转换器的层次结构: 而直接发送 Message: 解决方案 方案1:直接使用Message对象(推荐) 方案2:配置自定义MessageConverter 问题根因总结 经验教训 结论 最后最后附上序列化工具:


Apache Doris 与 ClickHouse:运维与开源闭源对比
SelectDB技术团队2025/10/16

引言 在当今数据驱动的商业环境中,OLAP(在线分析处理)数据库的选择对企业的数据分析能力和运维成本有着深远影响。Apache Doris 和 ClickHouse 作为业界领先的高性能 OLAP 数据库,各自在不同场景下展现出独特优势。 Apache Doris 以其优秀的宽表查询能力、多表 JOIN 性能、实时更新、search 以及湖加速特性而著称。ClickHouse 同样在宽表处理方面表现出色,其丰富的分析函数库和高性能单表聚合能力备受青睐。 然而,从运维角度来看,两者在存算分离

首页编辑器站点地图

Copyright © 2025 聚合阅读

License: CC BY-SA 4.0