C++ 回调函数及 std::function 与 std::bind

回调函数是做为参数传递的一种函数,在早期C样式编程当中,回调函数必须依赖函数指针来实现。

而后的C++语言当中,又引入了 std::function 与 std::bind 来配合进行回调函数实现。

标准库中有大量函数应用到了回调函数,其中 std::sort 就是一个经典例子。

回调函数的创建步骤大概为:

1,声明一个函数指针类型。

2,拟写使用回调函数的函数,将函数指针类型及变量名声明作为参数传递。

3,拟写符合函数指针类型的实现函数,将实现函数的指针作为参数传递给使用它的函数。

下面演示了一个最简单的回调函数定义及使用:

可以看到,我们通过语法:

来定义了回调函数的指针类型,包括返回值类型、(*类型名)函数指针、参数表。

继而又定义并且实现了回调函数的使用者函数:

再去定义并实现符合函数指针类型的实现函数:

必须要注意的是, 实现函数的类型必须要和函数指针的类型声明一致,也就是返回值和参数表(个数、类型)要完全一致。

这样就完成了一个简单且最基本的回调函数。

那么,回调函数是什么情况下使用的呢?

举个最经典的例子就是 std::sort,当你需要给一个存储有自定义结构体的 vector 进行排序时,编译器是无法知道如何对自定义结构体进行排序的。

这时候就需要实现一个回调函数来告诉编译器如何排序:

这样,就相当于自定义了 struct 的排序规则,自然编译器也可以使用 std::sort 对自定义 struct 进行排序操作。

上面演示了最简单的回调函数创建及使用,然而,上面的代码却出现了一个局限性,就是如果需要去回调一个类成员函数,函数指针则无法指向类成员函数。

在基本C样式面向过程编程当中,这种局限性并不那么明显甚至可以说不存在。但是到了C++当中,这种弊端就显而易见了,解决方式便是使用 std::function 与 std::bind 互相配合。

它们的头文件是 #include

std::function 是一个 模板类。作用是对C++中的可调用对象进行包装,例如普通函数、成员函数、模板函数、静态函数、lambda表达式等。

语法是:

可以看到,这个模板类当中对类型的声明方式是 < 返回值类型 ( 参数类型1, 参数类型2, …) >。

你几乎可以拿它包装任何可调用对象,只需简单粗暴的将可调用对象作为右值赋值给它:

那么如何使用它来调用类成员函数呢?这时就需要用到经常与 std::function 配合使用的 std::bind。

它是一个 基于模板的函数,顾明思意它的作用是绑定并返回一个 std::function 对象。

那么什么是”绑定”?它本身作为延迟计算的思想的一种实现, 作为一个调用过程当中的转发者而存在,返回一个 std::function 对象

它与 std::function 不同的是, function 是模板类,bind 是模板函数,而 bind 返回的可调用对象可以直接给 function 进行包装并保存

为什么要进行”包装”与”转发”呢?

首先,不规范的解释是,function 的作用是包装,它可以包装类成员函数,但却无法生成类成员函数的可调用对象。而 std::bind 则是可以生成。

因此,function 与 bind 结合后,便成为了 C++ 中类成员函数作为回调函数的一种规范的实现方式。

std::bind 的语法是:

当用作普通函数的绑定时,第一个参数是可调用对象(普通函数、lambda等),而第二个参数开始对应可调用对象的参数表。

std::placeholders::_1 代表可调用对象的第一个参数,_2就代表第二个参数,依此类推。

当用作类成员函数的绑定时,第一个参数仍然是作为类成员的可调用对象引用,第二个参数则是对象的指针,而第三个参数开始对应可调用对象的参数表。

同样使用 std::placeholders::_* 依次向后推。

所以,与 std::function 相结合,便可以实现对类成员函数的调用:

对 std::bind 的额外注解:

1,调用指向非静态成员函数指针或指向非静态数据成员指针时,首参数必须是引用或指针(可以包含智能指针,如 std::shared_ptr 与 std::unique_ptr),指向将访问其成员的对象。
2,到 bind 的参数被复制或移动,而且决不按引用传递,除非包装于 std::ref 或 std::cref 。
3,允许同一 bind 表达式中的多重占位符(例如多个 _1 ),但结果仅若对应参数( u1 )是左值或不可移动右值才良好定义。

Original: https://www.cnblogs.com/airchip/p/15965483.html
Author: 芯片烤电池
Title: C++ 回调函数及 std::function 与 std::bind

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/642582/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 奇安信服务端一二面面经(来源牛客)

    一.一面 应用层——HTTP: ​ 当输入URL后,对URL进行解析。​ URL解析方式如下:​ https://www.baidu.com/​ https:代表访问数组的协议(h…

    技术杂谈 2023年7月11日
    082
  • Linux安装cmatrix代码雨教程

    一:介绍 cmatrix代码雨是Linux的系统屏保界面;执行cmatrix不仅可以练习简单的编译安装软件三部曲,还可以执行cmatrix命令做出代码雨,提升文化实力 二:成品演示…

    技术杂谈 2023年7月11日
    071
  • Linux Accounting(中文翻译)(1):Pressure Stall Information

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    技术杂谈 2023年7月11日
    073
  • docker学习:docker镜像

    镜像是什么 镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。 Uni…

    技术杂谈 2023年7月10日
    0106
  • K8s配置存活、就绪和启动探测器

    这篇文章介绍如何给容器配置存活、就绪和启动探测器。 kubelet 使用 存活探测器来知道什么时候要重启容器。 例如,存活探测器可以捕捉到死锁(应用程序在运行,但是无法继续执行后面…

    技术杂谈 2023年5月30日
    078
  • list,map,set的区别

    list,map,set的区别 (首先假定小猪都是同一个细胞克隆出来的) List = 排成一长队的小猪 Map = 放在一个个,有房间号的屋子里面的一群小猪 Set = 一群小猪…

    技术杂谈 2023年5月31日
    071
  • 路径计数动态规划dp题目

    问题描述 输入格式 输出格式 样例 代码 补充 题解分析等闲了就补上(doge),慢慢更新ing 路径计数 比较经典常见的动态规划dp题目了 问题描述 有一个n ×n的网格,有些格…

    技术杂谈 2023年7月23日
    063
  • Kubernetes集群架构与组件介绍

    一、Master组件(管理节点)1.kube-apiserverKubernetes API,集群的统一入口,各组件协调者,以RESTfulAPI提供接口服务,所有对象资源的增删改…

    技术杂谈 2023年5月30日
    095
  • Nginx 开源版编译安装教程

    本文示例在虚拟机 Rocky Linux 8.5 系统中编译安装 Nginx 开源版软件。 关于虚拟机 Rocky Linux 8.5 系统的安装配置教程可参考这篇文章:VMwar…

    技术杂谈 2023年7月11日
    086
  • 【SSM框架】MyBatis笔记 – 表之间的关联关系;MyBatis事务;MyBatis缓存机制;ORM概述

    一、表之间的关联关系: 关联关系是有方向的。 1、四种关联关系: 1)一对多关联:一个老师可以教多个学生,多个学生只有一个老师来教,站在老师方,就是一对多关联。 2)多对一关联:一…

    技术杂谈 2023年7月10日
    079
  • wasm示例 js canvas 动画示例

    3d迷宫移动:https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/A_basic_ray-caster C:\d…

    技术杂谈 2023年5月31日
    092
  • Launch Shopify主题模板设置修改

    Launch是Kickstarter风格的Shopify主题,旨在将初创公司变成成功的商店。展示细节并讲述您的产品故事。支持OS 2.0,适合‎健康与美容, 家庭与园艺, 运动与休…

    技术杂谈 2023年5月30日
    098
  • AOP面向切面编程简单介绍与应用

    AOP面向切面编程 什么是AOP AOP (Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技…

    技术杂谈 2023年7月10日
    076
  • Element-DatePicker的宽度

    打开一个vue文件,添加DatePicker日期选择器组件,设置默认日期为null。如图 Original: https://www.cnblogs.com/beichengshi…

    技术杂谈 2023年7月10日
    064
  • Java中方法的定义和使用

    方法的定义和使用 注意事项: 1.方法与方法之间是 平级关系 不可以嵌套定义 2.方法的位置 可以在类{}中任意位置 3.方法定义之后 之后被调用 才能被执行 4.return 关…

    技术杂谈 2023年6月21日
    088
  • 9月份全球认证标准更新(欧盟,俄罗斯)

    欧盟无线产品RED 指令2014/53/EU 已于今年2月将网路安全纳入指令要求,并将于2024年8月1日开始强制实施。 ● 评估重点 确保设备不会破坏网路及其功能或误用网路资源,…

    技术杂谈 2023年6月21日
    0118
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球