【编程技巧】C++如何使用std::map管理std::function函数指针
一、问题背景
开发过程中遇到了需要根据const字符串调用不同函数的要求。在开发过程中为了快速实现功能,实际使用了if else等判断实现了不同函数的调用,徒增了不少代码行数。
明知道可以采用map管理函数指针,但是没有具体实现过,所以不敢贸然采用。为避免凑代码行数之嫌,决定使用这种方式去更新写法,现将学习过程记录下来。
二、std::map管理函数指针
使用 std::map
(或其他关联容器,如 std::unordered_map
)来管理 function
函数指针,可以为程序设计带来许多优势,尤其在需要动态管理和调用函数的场景中。具体包括以下优点:
- 动态映射与查找:使用
std::map
可以将特定的标识符(如std::string
、int
等)与函数指针或std::function
关联起来,使得程序能够根据需求在运行时动态查找并调用函数,而无需编写复杂的switch-case
或if-else
语句。 - 简化代码结构,易于扩展:当有新的功能需要添加时,只需向
std::map
中插入新的函数指针即可,而不必更改原有的代码逻辑。这样可以极大地提高代码的可维护性和扩展性。如果将来需要替换或修改某个功能,只需更新映射中的函数指针即可。 - 高效查询与调用:
std::map
和std::unordered_map
提供了高效的查找功能。std::map
是一个基于红黑树实现的有序容器,查找时间复杂度为 O(log n),而std::unordered_map
是基于哈希表实现的无序容器,查找时间复杂度为平均 O(1)。使用这些容器管理函数指针,程序可以快速找到并执行目标函数。
三、std::function
(1)std::function定义
类模板std::function
是 C++ 标准库中的一个通用多态函数包装器,位于 <functional>
头文件中。它可以用来存储、复制和调用任何符合特定函数签名的可调用对象,比如普通函数、lambda 表达式、std::bind
生成的函数对象,或者是函数对象类的实例。
存储的可调用对象称为std::function
的目标。如果std::function
不包含目标,则称为空函数。调用空的std::function
的目标函数会产生std::bad_function_call
异常。
(2)std::function语法
#include <functional>
std::function<ReturnType(ArgTypes...)>
ReturnType:指定函数的返回类型。
ArgTypes…:指定函数的参数类型列表。
(3)std::function 与传统函数指针的区别
std::function 是 C++11 引入的一个模板类,它可以存储、复制和调用任何可调用对象,包括函数指针、lambda 表达式、函数对象等。而传统函数指针则只能指向函数。
相较于传统函数指针,std::function具有更强的类型安全性,但性能上略低于传统函数指针。
四、具体实现
实现步骤如下:
- 采用别名
FunctionPtr
代替std::function<void(int, int)>
。 - 定义具名函数
void func1(int, int)
和void func2(int, int)
,分别实现加法和乘法。 - 定义匿名函数
void(int, int)
实现减法。 - 定义
std::map<std::string, std::shared_ptr<FunctionPtr>> functionMap;
用于管理上述函数。 - 此时
functionMap
能够根据传入的string不同调用不同的函数。
#include <iostream>
#include <map>
#include <memory>
#include <functional>using FunctionPtr = std::function<void(int, int)>;void func1(int x, int y) {std::cout << "In func1, x + y = " << x + y << std::endl;
}void func2(int x, int y) {std::cout << "In func2, x * y = " << x * y << std::endl;
}int main() {std::map<std::string, std::shared_ptr<FunctionPtr>> functionMap;functionMap["func1"] = std::make_shared<FunctionPtr>(func1);functionMap["func2"] = std::make_shared<FunctionPtr>(func2);functionMap["func3"] = std::make_shared<FunctionPtr>([](int x, int y) -> void {std::cout << "In func3, x - y = " << x - y << std::endl;});for (const auto &functionPair : functionMap) {auto funcName = functionPair.first;std::cout << "In main, funcName = " << funcName << std::endl;auto function = functionPair.second;if (function != nullptr) {(*function)(1,2);}}return 0;
}
五、参考文献
- Cpp Reference之std::map:https://en.cppreference.com/w/cpp/container/map。
- Cpp Reference之std::function:https://en.cppreference.com/w/cpp/utility/functional/function
相关文章:

【编程技巧】C++如何使用std::map管理std::function函数指针
一、问题背景 开发过程中遇到了需要根据const字符串调用不同函数的要求。在开发过程中为了快速实现功能,实际使用了if else等判断实现了不同函数的调用,徒增了不少代码行数。 明知道可以采用map管理函数指针,但是没有具体实现过,…...

导航栏小案例
实现类似于这样的效果 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>导航栏</title><style>*{margin: 0;padding: 0;}.div1{width: 100%;height: 60px;/* border: 1px solid blue; */background-color:rgb(…...

MyBatis一文入门精通,面试题(含答案)
一、MyBatis详细介绍 MyBatis 是一个流行的 Java 持久层框架,主要用于简化 SQL 数据库操作。它的设计初衷是通过 XML 或注解的方式配置和执行 SQL 语句,使得数据库操作更加灵活、方便和高效。相比于传统的 JDBC,MyBatis 提供了一些关键优势&…...

Ubuntu18.04服务器非root用户在虚拟环境下的python版本设定
最近需要跑一个python3.9.16版本的代码,Ubuntu18.04服务器上是上次博客中已经定死的python3.8.0版本 需要创建一个虚拟环境,并且在虚拟环境中配置python3.9.16版本 只需要创建一个虚拟环境 conda create -n yyy python3.9.16yyy是你的虚拟环境名字 创建…...

CodeS:构建用于文本到 SQL 的开源语言模型
发布于:2024 年 10 月 29 日 #RAG #Text2 SQL #NL2 SQL 语言模型在将自然语言问题转换为 SQL 查询(文本到 SQL )的任务中显示出良好的性能。然而,大多数最先进的 (SOTA) 方法都依赖于强大但闭源的大型语言…...

HTML 基础概念:什么是 HTML ? HTML 的构成 与 HTML 基本文档结构
文章目录 什么是 HTML ?HTML 的构成 ?什么是 HTML 元素?HTML 元素的组成部分HTML 元素的特点 HTML 基本文档结构如何打开新建的 HTML 文件代码查看 什么是 HTML ? HTML(超文本标记语言,HyperText Markup L…...

18 Docker容器集群网络架构:一、etcd 概述
文章目录 Docker容器集群网络架构:一、etcd概述1.1 etcd 的基本概念和特点1.1.1 定义1.1.2 特点1.2 etcd 在 Docker 集群网络中的作用1.3 etcd 集群的架构和原理1.3.1 架构1.3.2 原理Docker容器集群网络架构:一、etcd概述 etcd是一个高可用的分布式键值存储系统,它主要用于…...

R语言贝叶斯分层、层次(Hierarchical Bayesian)模型房价数据空间分析
原文链接:https://tecdat.cn/?p38077 本文主要探讨了贝叶斯分层模型在分析区域数据方面的应用,以房价数据为例,详细阐述了如何帮助客户利用R进行模型拟合、分析及结果解读,展示了该方法在处理空间相关数据时的灵活性和有效性。&a…...

SpringBoot 在初始化加载无法使用@Value的时候读取配置文件教程
怀旧网个人博客地址:怀旧网,博客详情:SpringBoot 在初始化加载无法使用Value的时候读取配置文件教程 读取数据库数据案例 // 创建YamlPropertiesFactoryBean对象 YamlPropertiesFactoryBean factory new YamlPropertiesFactoryBean(); // …...

基于MATLAB的身份证号码识别系统
课题介绍 本课题为基于连通域分割和模板匹配的二代居民身份证号码识别系统,带有一个GUI人机交互界面。可以识别数十张身份证图片。 首先从身份证图像上获取0~9和X共十一个号码字符的样本图像作为后续识别的字符库样本,其次将待测身份证图像…...

【人工智能-初级】练习题:matplotlib基础练习30例
练习 1: 画折线图 import matplotlib.pyplot as plt x = [1, 2, 3, 4, 5] y = [10, 20, 25, 30, 40] 使用 plt.plot() 画出折线图,适用于连续数据的可视化 plt.plot(x, y) plt.xlabel(‘X 轴’) plt.ylabel(‘Y 轴’) plt.title(‘简单折线图’) plt.show() 练习 2: 画散…...

【002】基于SpringBoot+thymeleaf实现的蓝天幼儿园管理系统
基于SpringBootthymeleaf实现的蓝天幼儿园管理系统 文章目录 系统说明技术选型成果展示账号地址及其他说明源码获取 系统说明 基于SpringBootthymeleaf实现的蓝天幼儿园管理系统是为幼儿园提供的一套管理平台,可以提高幼儿园信息管理的准确性,系统将信息…...

nvm详解
本文借鉴转载于 nvm文档手册 文章目录 1.nvm是什么?2.nvm安装2.1 window上安装下载链接安装步骤 2.2 Mac上安装使用homebrew 安装 nvm 3.nvm使用指令 1.nvm是什么? nvm(Node Version Manager)是一个用于管理和切换不同版本 Node.…...

Lucene的概述与应用场景(1)
文章目录 第1章 Lucene概述1.1 搜索的实现方案1.1.1 传统实现方案1.1.2 Lucene实现方案 1.2 数据查询方法1.1.1 顺序扫描法1.1.2 倒排索引法 1.3 Lucene相关概念1.3.1 文档对象1.3.2 域对象1)分词2)索引3)存储 1.3.3 常用的Field种类 1.4 分词…...

11.3笔记
在C#中,静态类和普通类(实例类)有一些关键的区别: 实例化: 普通类:可以被实例化,即创建对象。每个对象都有自己的状态和方法。静态类:不能被实例化,它们不包含构造函数&a…...
数据结构之线段树
线段树 线段树(Segment Tree)是一种高效的数据结构,广泛应用于计算机科学和算法中,特别是在处理区间查询和更新问题时表现出色。以下是对线段树的详细解释: 一、基本概念 线段树是一种二叉搜索树,是算法竞…...

vue 快速入门
文章目录 一、插值表达式 {{}}二、Vue 指令2.1 v-text 和 v-html:2.2 v-if 和 v-show:2.3 v-on:2.4 v-bind 和 v-model:2.5 v-for: 三、生命周期四、Vue 组件库 Element五、Vue 路由 本文章适用于后端人员,…...

iframe视频宽度高度自适应( pc+移动都可以用,jq写法 )
注意:要引入jquery 可以直接使用弹框播放iframe 一、创建 index.html <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style>.modal {/* 默认隐藏 */display: none;position: fixed;z-i…...

Observability:OpenTelemetry Elastic 分发简介
作者:来自 Elastic Alexander Wert•Miguel Luna•Bahubali Shetti Elastic 自豪地推出了 Elastic Distributions of OpenTelemetry (EDOT),其中包含 Elastic 版本的 OpenTelemetry Collector 和多种语言 SDK,如 Python、Java、.NET 和 NodeJ…...

golang的RSA加密解密
参考:https://blog.csdn.net/lady_killer9/article/details/118026802 1.加密解密工具类PasswordUtil.go package utilimport ("crypto/rand""crypto/rsa""crypto/x509""encoding/pem""fmt""log"&qu…...

深度学习-梯度消失/爆炸产生的原因、解决方法
在深度学习模型中,梯度消失和梯度爆炸现象是限制深层神经网络有效训练的主要问题之一,这两个现象从本质上来说是由链式求导过程中梯度的缩小或增大引起的。特别是在深层网络中,若初始梯度在反向传播过程中逐层被放大或缩小,最后导…...

MVC(Model-View-Controller)模式概述
MVC(Model-View-Controller)是一种设计模式,最初由 Trygve Reenskaug 在 1970 年代提出,并在 Smalltalk 编程环境中得到了广泛应用。MVC 模式旨在实现用户界面和业务逻辑的分离,以增强应用程序的可维护性、可扩展性和复…...

数据结构 —— 红黑树
目录 1. 初识红黑树 1.1 红黑树的概念 1.2 红⿊树的规则 1.3 红黑树如何确保最长路径不超过最短路径的2倍 1.4 红黑树的效率:O(logN) 2. 红黑树的实现 2.1 红黑树的基础结构框架 2.2 红黑树的插⼊ 2.2.1 情况1:变色 2.2.2 情况2:单旋变色 2.2…...

《功能高分子学报》
《功能高分子学报》 中国标准连续出版物号:CN 31-1633/O6,国际标准连续出版物号:ISSN 1008-9357,邮发代号:4-629,刊期:双月刊。 《功能高分子学报》主要刊登功能高分子和其他高分子领域具有创新意义的学术…...

Linux特种文件系统--tmpfs文件系统
tmpfs类似于RamDisk(只能使用物理内存),使用虚拟内存(简称VM)子系统的页面存储文件。tmpfs完全依赖VM,遵循子系统的整体调度策略。说白了tmpfs跟普通进程差不多,使用的都是某种形式的虚拟内存&a…...

《基于STMF103的FreeRTOS内核移植》
目录 1.FreeRTOS资料下载与出处 1.1官网下载,网址:www.freertos.org 1.2在正点原子官网,任意STM32F1的开发板资料A盘里, 2.FreeRTOS移植重要文件讲解 2.1 FreeRTOS与FreeRTOS-Plus文件夹 2.2 Demo、Lincence、Source ●Demo文件…...

一七二、Vue3性能优化方式
Vue 3 的性能优化相较于 Vue 2 有了显著提升,利用新特性和改进方法可以更高效地构建和优化应用。以下是 Vue 3 的常见性能优化方法及示例。 1. 使用组合式 API (Composition API) Vue 3 引入的组合式 API,通过逻辑拆分和复用来实现更高效的代码组织和性…...

软件测试--BUG篇
博主主页: 码农派大星. 数据结构专栏:Java数据结构 数据库专栏:MySQL数据库 JavaEE专栏:JavaEE 软件测试专栏:软件测试 关注博主带你了解更多知识 目录 1. 软件测试的⽣命周期 2. BUG 1. BUG 的概念 2. 描述bug的要素 3.bug级别 4.bug的⽣命周期 5 与开发产⽣争执怎…...

Scikit-learn和Keras简介
一,Scikit-learn是一个开源的机器学习库,用于Python编程语言。它建立在NumPy、SciPy和matplotlib这些科学计算库之上,提供了简单有效的数据挖掘和数据分析工具。Scikit-learn库包含了许多用于分类、回归、聚类和降维的算法,包括支…...

python在word的页脚插入页码
1、插入简易页码 import win32com.client as win32 from win32com.client import constants import osdoc_app win32.gencache.EnsureDispatch(Word.Application)#打开word应用程序 doc_app.Visible Truedoc doc_app.Documents.Add() footer doc.Sections(1).Footers(cons…...