当前位置: 首页 > article >正文

c++中的静态多态和动态多态简介

在 C++ 中,多态性(Polymorphism) 分为 静态多态(Static Polymorphism) 和 动态多态(Dynamic Polymorphism),二者通过不同的机制实现代码的灵活性。以下是详细对比和核心要点:

目录

一、静态多态(编译时多态)

定义

实现方式

1.函数重载(Function Overloading)

2.模板(Templates)

3.运算符重载(Operator Overloading)

特点

典型应用

二、动态多态(运行时多态)

定义

实现方式

特点

典型应用

三、核心区别对比表

四、选择策略

使用静态多态的场景

使用动态多态的场景

五、混合使用技术

CRTP(奇异递归模板模式)

类型擦除(Type Erasure)

六、性能对比数据

总结建议


一、静态多态(编译时多态)

定义

在编译期间确定具体调用的函数或操作,不依赖运行时类型信息。

实现方式

1.函数重载(Function Overloading)

void print(int x) { /* 处理整型 */ }
void print(double x) { /* 处理浮点型 */ }

         编译器根据参数类型选择函数。

2.模板(Templates)

template <typename T>
T add(T a, T b) { return a + b; }add(1, 2);    // 实例化为 int 版本
add(1.0, 2.0); // 实例化为 double 版本

         编译时生成具体类型的代码。

3.运算符重载(Operator Overloading)

Vector operator+(const Vector& a, const Vector& b) { return Vector(a.x + b.x, a.y + b.y);
}

特点

  • 优点

    • 零运行时开销(无虚函数调用)

    • 支持泛型编程(如 STL 容器和算法)

  • 缺点

    • 编译时间增加(模板实例化)

    • 错误信息复杂(模板报错难以理解)

典型应用

  • STL 容器(vector<T>map<K,V>

  • 泛型算法(std::sortstd::transform


二、动态多态(运行时多态)

定义

在程序运行期间根据对象类型动态决定调用的函数。

实现方式

  1. 虚函数(Virtual Functions)

    class Shape {
    public:virtual void draw() = 0; // 纯虚函数
    };class Circle : public Shape {
    public:void draw() override { /* 画圆 */ }
    };Shape* shape = new Circle();
    shape->draw(); // 运行时调用 Circle::draw()
  2. 虚表(vtable)机制

    • 每个多态类有一个虚函数表

    • 对象包含指向虚表的指针(vptr)

特点

  • 优点

    • 支持运行时类型识别(RTTI)

    • 代码扩展性强(新增派生类无需修改基类)

  • 缺点

    • 运行时开销(虚表查找,通常多一次指针间接访问)

    • 对象内存增加(vptr 占用空间)

典型应用

  • GUI 框架(不同控件的事件处理)

  • 插件系统(动态加载派生类)


三、核心区别对比表

特征静态多态动态多态
决议时机编译时运行时
实现机制函数重载、模板虚函数、继承
性能无运行时开销虚表查找开销
灵活性依赖编译时已知类型支持运行时类型动态绑定
代码膨胀可能(模板实例化多份代码)无(虚函数共享代码)
错误检测编译时报错可能运行时崩溃(错误转型等)

四、选择策略

使用静态多态的场景

  • 需要高性能(如数值计算、游戏引擎)

  • 类型在编译时已知(如泛型算法)

  • 避免虚函数开销(嵌入式系统开发)

示例

template <typename T>
void fastSort(T* arr, size_t size) { // 模板实现高效排序
}

使用动态多态的场景

  • 需要运行时扩展性(如插件架构)

  • 处理异构对象集合(如 GUI 控件管理)

  • 实现接口抽象(如设计模式中的策略模式)

示例

class PaymentStrategy {
public:virtual void pay(int amount) = 0;
};class CreditCardPayment : public PaymentStrategy {
public:void pay(int amount) override { /* 信用卡支付逻辑 */ }
};// 运行时选择支付方式
PaymentStrategy* strategy = new CreditCardPayment();
strategy->pay(100);

五、混合使用技术

CRTP(奇异递归模板模式)

结合静态多态的高效与动态多态的接口统一性:

template <typename Derived>
class Base {
public:void interface() {static_cast<Derived*>(this)->implementation();}
};class Derived : public Base<Derived> {
public:void implementation() { /* 具体实现 */ }
};

类型擦除(Type Erasure)

使用 std::function 或自定义包装器实现动态行为:

class AnyDrawable {struct Concept {virtual ~Concept() = default;virtual void draw() = 0;};template <typename T>struct Model : Concept {T obj;void draw() override { obj.draw(); }};std::unique_ptr<Concept> ptr;
public:template <typename T>AnyDrawable(T&& obj) : ptr(new Model<std::decay_t<T>>{std::forward<T>(obj)}) {}void draw() { ptr->draw(); }
};// 使用
AnyDrawable shape1 = Circle();
AnyDrawable shape2 = Square();
shape1.draw(); // 动态调用

六、性能对比数据

操作静态多态(模板)动态多态(虚函数)
函数调用延迟1.2 ns3.5 ns
10^6 次调用耗时1.2 ms3.5 ms
内存占用(每个对象)0 额外字节8 字节(vptr)
代码体积增加可能较大(实例化)固定

总结建议

  1. 优先选择静态多态

    • 当性能要求严格且类型已知时

    • 使用模板和重载减少运行时开销

  2. 必须使用动态多态

    • 需要运行时灵活扩展时

    • 处理未知派生类对象集合

  3. 混合方案

    • 对性能敏感模块使用 CRTP

    • 对接口抽象层使用虚函数

理解二者的区别与适用场景,可帮助开发者在效率与灵活性之间找到最佳平衡。

相关文章:

c++中的静态多态和动态多态简介

在 C 中&#xff0c;多态性&#xff08;Polymorphism&#xff09; 分为 静态多态&#xff08;Static Polymorphism&#xff09; 和 动态多态&#xff08;Dynamic Polymorphism&#xff09;&#xff0c;二者通过不同的机制实现代码的灵活性。以下是详细对比和核心要点&#xff1…...

如何通过 LlamaIndex 将数据导入 Elasticsearch

作者&#xff1a;来自 Elastic Andre Luiz 逐步介绍如何使用 RAG 和 LlamaIndex 提取数据并进行搜索。 在本文中&#xff0c;我们将使用 LlamaIndex 来索引数据&#xff0c;从而实现一个常见问题搜索引擎。 Elasticsearch 将作为我们的向量数据库&#xff0c;实现向量搜索&am…...

Boosting

Boosting 学习目标 知道boosting集成原理和实现过程知道bagging和boosting集成的区别知道AdaBoost集成原理 Boosting思想 Boosting思想图 每一个训练器重点关注前一个训练器不足的地方进行训练通过加权投票的方式&#xff0c;得出预测结果串行的训练方式 1 什么是boosting 随着…...

【通俗讲解电子电路】——从零开始理解生活中的电路(一)

导言&#xff1a;电子电路为什么重要&#xff1f; ——看不见的“魔法”&#xff0c;如何驱动你的生活&#xff1f; 清晨&#xff0c;当你的手机闹钟响起时&#xff0c;你可能不会想到&#xff0c;是电子电路在精准控制着时间的跳动&#xff1b;当你用微波炉加热早餐时&#…...

LeetCode72编辑距离(动态规划)

给你两个单词 word1 和 word2&#xff0c; 请返回将 word1 转换成 word2 所使用的最少操作数 。 你可以对一个单词进行如下三种操作&#xff1a; 插入一个字符 删除一个字符 替换一个字符 示例 1&#xff1a; 输入&#xff1a;word1 “horse”, word2 “ros” 输出&#xf…...

rabbitmq单向ssl认证配置与最佳实践(适用于各大云厂商)

背景 这里后补直接上代码 最佳实践 主要从两个方面保证消息不丢失 RabbitMQ方面 创建队列时开启持久化创建交换器时开启持久化创建镜像队列&#xff08;可选&#xff09;开启延迟队列&#xff08;可选&#xff09; 代码层面 开启生产者到交换器回调参数开启交换器到队列…...

【K8S】Kubernetes 基本架构、节点类型及运行流程详解(附架构图及流程图)

Kubernetes 架构 k8s 集群 多个 master node 多个 work nodeMaster 节点&#xff08;主节点&#xff09;&#xff1a;负责集群的管理任务&#xff0c;包括调度容器、维护集群状态、监控集群、管理服务发现等。Worker 节点&#xff08;工作节点&#xff09;&#xff1a;实际运…...

Windows版FFmpeg使用及B站视频下载示例python源码

Windows版FFmpeg使用及B站视频下载示例python源码 FFmpeg介绍和下载 FFmpeg 是一个功能强大、灵活且广泛使用的多媒体处理工具&#xff0c;无论是在专业领域还是日常使用中&#xff0c;都能满足各种多媒体处理需求。FFmpeg 是一个开源项目&#xff0c;遵循 LGPL 或 GPL 许可。…...

飞书考勤Excel导入到自己系统

此篇主要用于记录Excel一行中&#xff0c;单条数据的日期拿取&#xff0c;并判断上下班打卡情况。代码可能满足不了大部分需求&#xff0c;目前只够本公司用&#xff0c;如果需要&#xff0c;可以参考。 需要把飞书月度汇总的考勤表导入系统中可以参考下。 下图为需要获取的年…...

【leetcode hot 100 560】和为K的子数组

解法一&#xff1a;用左右指针寻找字串&#xff0c;如果和>k&#xff0c;则减少一个数&#xff08;left&#xff09;&#xff1b;如果和<k&#xff0c;则加上一个数&#xff08;right&#xff09;。 class Solution {public int subarraySum(int[] nums, int k) {int nu…...

EGO-Planner的无人机视觉选择(yolov5和yolov8)

EGO-Planner的无人机视觉选择&#xff08;yolov5和yolov8&#xff09; 效果 yolov5检测效果 yolov8检测效果 一、YOLOv8 vs YOLOv5&#xff1a;关键差异解析 1. 训练效率&#xff1a;为何YOLOv8更快&#xff1f; 架构轻量化 YOLOv8采用C2f模块&#xff08;Cross Stage Partia…...

C++ | 面向对象 | 类

&#x1f47b;类 &#x1f47e;语法格式 class className{Access specifiers: // 访问权限DataType variable; // 变量returnType functions() { } // 方法 };&#x1f47e;访问权限 class className {public:// 公有成员protected:// 受保护成员private:// 私有成员 }…...

性能测试分析和调优

步骤 性能调优的步骤 性能调优的步骤&#xff1a; 1.确定问题&#xff1a;根据性能测试的结果来分析确定bug。–测试人员职责 2.分析原因&#xff1a;分析问题产生的原因。----开发人员职责 3.给出解决方案&#xff1a;可以是修改软件配置、增加硬件资源配置、修改代码等----…...

阿里云oss文件上传springboot若依java

一、第一步 引入依赖 <!-- 阿里云OSS --> <dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId> </dependency> 二、第二步 application.yml #阿里云oss服务配置 aliyun:oss:endpoint: …...

【自学笔记】Oracle基础知识点总览-持续更新

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Oracle 数据库基础知识点总览1. 数据库安装与配置2. SQL基础3. PL/SQL基础4. 数据库管理5. 高级主题 总结 Oracle 数据库基础知识点总览 1. 数据库安装与配置 安装…...

使用create_sql_query_chain工具根据自然语言问题生成SQL查询,踩坑版

1. 开启调试模式 from langchain import debugdebug True # 启用调试模式说明&#xff1a; 这里从 langchain 库中导入了一个名为 debug 的变量&#xff08;或模块&#xff09;&#xff0c;然后将它设置为 True。这通常用来启用调试模式&#xff0c;方便开发者在程序运行时看…...

PyInstaller 打包python 程序 成 可执行文件

pyinstaller --onefile --name my_project --add-data "config/config.json:config" main.py 要将整个 Python 项目打包成一个可执行文件&#xff0c;可以使用 PyInstaller 来完成这个任务。以下是如何将整个项目打包成可执行文件的步骤&#xff1a; 1. 安装 PyIns…...

生鲜行业智能化供应链解决方案技术白皮书

行业痛点与技术挑战 损耗控制难题 行业平均损耗率达18%-25%&#xff0c;需构建动态定价模型与智能分拣系统 冷链管理复杂度 全程温控数据采集点超过23个/车次&#xff0c;异常响应延迟需压缩至90秒内 供需预测偏差 传统模式预测准确率不足65%&#xff0c;亟需AI驱动需求预测体…...

preg_replace 与 str_replace 的比较与选择

preg_replace 与 str_replace 的比较与选择 ——PHP字符串处理的核心工具深度解析 一、核心功能定位 在PHP的字符串处理中&#xff0c;str_replace和preg_replace是两种最常用的替换函数&#xff0c;但其设计目标和应用场景存在本质差异&#xff1a; str_replace 简单字符串替…...

无人机自主导航与避障技术!

自主导航的实现 环境感知&#xff1a;通过传感器&#xff08;如摄像头、激光雷达、超声波传感器等&#xff09;获取周围环境信息。 地图构建&#xff1a;利用SLAM&#xff08;同步定位与地图构建&#xff09;技术&#xff0c;实时生成环境地图并确定无人机的位置。 路径规划…...

密码学(哈希函数)

4.1 Hash函数与数据完整性 数据完整性&#xff1a; 检测传输消息&#xff08;加密或未加密&#xff09;的修改。 密码学Hash函数&#xff1a; 构建某些数据的简短“指纹”&#xff1b;如果数据被篡改&#xff0c;则该指纹&#xff08;以高概率&#xff09;不再有效。Hash函数…...

深入探索 STM32 微控制器:从基础到实践

一、引言 在当今的嵌入式系统领域&#xff0c;STM32 系列微控制器凭借其高性能、低功耗、丰富的外设以及广泛的应用场景&#xff0c;成为了众多开发者的首选。无论是在工业控制、智能家居、医疗设备&#xff0c;还是在消费电子等领域&#xff0c;STM32 都展现出了强大的生命力…...

React 常见面试题及答案

记录面试过程 常见问题&#xff0c;如有错误&#xff0c;欢迎批评指正 1. 什么是虚拟DOM&#xff1f;为什么它提高了性能&#xff1f; 虚拟DOM是React创建的一个轻量级JavaScript对象&#xff0c;表示真实DOM的结构。当状态变化时&#xff0c;React会生成新的虚拟DOM&#xf…...

SpringSecurity 实现token 认证

配置类 Configuration EnableWebSecurity EnableGlobalMethodSecurity(prePostEnabledtrue) public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { Bean Override public AuthenticationManager authenticationManagerBean() throws Exception {return s…...

【详解 | 辨析】“单跳多跳,单天线多天线,单信道多信道” 之间的对比

文章目录 1. 单跳 & 多跳2. 单天线 & 多天线3. 单信道 & 多信道4. 小区内通信 & 小区间通信5. 更多辨析5.1 无线Mesh网络&#xff0c;Ad Hoc网络&#xff0c;无线传感器网络&#xff08;MSN&#xff09;5.2 “单天线/多天线”与“单信道/多信道”的区别 6. 工业…...

嵌入式开发工程师笔试面试指南-HR面试常见问题汇总

在嵌入式领域的招聘面试中,HR 通过一系列精心设计的问题,全面考察候选人的综合素质、专业能力以及与岗位的匹配度。以下从多个关键方面汇总了 HR 在嵌入式面试中常见的问题。 ** 一、语言表达方面 请简单介绍一下你自己这是面试开场常见问题,旨在让候选人做一个自我展示,…...

Docker 搭建 Gitlab 服务器 (完整详细版)

参考 Docker 搭建 Gitlab 服务器 (完整详细版)_docker gitlab-CSDN博客 Docker 安装 (完整详细版)_docker安装-CSDN博客 Docker 日常命令大全(完整详细版)_docker命令-CSDN博客 1、Gitlab镜像 # 查找Gitlab镜像 docker search gitlab # 拉取Gitlab镜像 docker pull gitlab/g…...

MongoDB安全管理

MongoDB如何鉴权 保证数据的安全性是数据库的重大职责之一。与大多数数据库一样&#xff0c;MongoDB内部提供了一套完整的权限防护机制。如下例所示&#xff1a; mongo --host 127.0.0.1 --port 27017 --username someone --password errorpass --authenticationDatabasestor…...

架构案例:从初创互联网公司到分布式存储与反应式编程框架的架构设计

文章目录 引言一、初创互联网公司架构演化案例1. 万级日订单级别架构2. 十万级日订单级别架构3. 百万级日订单级别架构 二、分布式存储系统 Doris 架构案例三、反应式编程框架架构案例总结 引言 分布式架构 今天我们将探讨三种不同类型的架构案例&#xff0c;分别探讨 一个初…...

神经网络之CNN图像识别(torch api 调用)

1.简介 CNN 是受生物学上感受野机制启发而提出的。它通过卷积操作自动提取数据中的特征&#xff0c;避免了传统机器学习方法中复杂的特征工程过程&#xff0c;能够自动学习到数据中的有效特征&#xff0c;从而进行分类、识别等任务。 2.结构 2.1卷积&#xff1a; 假设你有一…...