【C++】C++11的包装器:function与bind简介

【C++】C++11的包装器:function与bind简介

各位大佬好,我是落羽!一个坚持不断学习进步的学生。
如果您觉得我的文章还不错,欢迎多多互三分享交流,一起学习进步!
也欢迎关注我的blog主页:
落羽的落羽

文章目录

一、function

1. 概念

上一篇文章我们学习了lambda表达式的用法。

std::function是 C++11 标准库在 <functional> 头文件中引入的一个通用、多态的函数包装器。它的本质是一个类模板,可以包装、存储、复制和调用任何可调用对象(函数指针、仿函数、lambda表达式、bind表达式等),存储的可调用对象被称为function的目标。function不含目标则为空,调用空function的目标会抛异常。
函数指针、仿函数、lambda表达式等可调用对象的类型各不相同,function可以统一类型,对他们进行包装,这样在很多地方就方便声明可调用对象的类型。

2. 用法

在这里插入图片描述


以上是function的原型,使用语法为:

#include<functional> std::function<返回类型(参数类型1, 参数类型2,...)> 包装器名称;

来看一段代码实例:

#include<iostream>#include<functional>usingnamespace std;// 普通函数intadd(int a,int b){return a + b;}// Lambda表达式auto multiply =[](int a,int b){return a * b;};// 仿函数structSubtract{intoperator()(int a,int b)const{return a - b;}};intmain(){// 声明一个function,他可以包装一个返回int,接受两个int参数的可调用对象 function<int(int,int)> func;// 包装普通函数 func = add; cout <<"Add: "<<func(10,5)<< endl;// 输出 15// 包装 Lambda 表达式 func = multiply; cout <<"Multiply: "<<func(10,5)<< endl;// 输出 50// 包装仿函数对象 Subtract sub; func = sub; cout <<"Subtract: "<<func(10,5)<< endl;// 输出 5// 甚至可以包装一个临时的Lambda func =[](int a,int b){return a / b;}; cout <<"Divide: "<<func(10,5)<<std::endl;// 输出 2return0;}

有一个特殊的点是,类的成员函数也可以被包装,但成员函数必须要指定类域并且前面加上&才能获取地址,静态成员函数可以不加&,但是为了方便记忆,建议成员函数都加上吧。这时还有一个问题,普通成员函数还有一个隐含的this指针,在类外包装时,也一定要显式写出this指针参数类型,即当前类的指针类型:

classPlus{public:Plus(int n =10):_n(n){}staticintplusi(int a,int b){return a + b;}doubleplusd(double a,double b){return(a + b)* _n;}private:int _n;};intmain(){ function<int(int,int)> f =&Plus::plusi; cout <<f(1,1)<< endl;// 输出2 function<double(Plus*,double,double)> f1 =&Plus::plusd;//调用时实例化出一个对象取地址传参即可,或者传对象也可以 Plus pd cout <<f1(&pd,1.1,1.1)<< endl;// 输出22/*function<double(Plus, double, double)> f1 = &Plus::plusd; Plus pd cout << f1(pd, 1.1, 1.1) << endl; */return0;}

二、bind

1. 概念

std::bind是一个函数模板,也包含在<functional>中,是一个可调用对象的包装器,可以把他看做一个函数适配器,对接收的可调用对象处理后返回一个可调用对象。bind可以用来调整参数个数和参数顺序。

在这里插入图片描述

2. 用法

调用bind的一般形式为:auto newCallable = bind(callable, arg_list);其中newCallable本身是一个可调用对象,arg_list是一个用逗号分隔的参数列表,对应给定callable的参数。arg_list中的参数可能包含形如_n的占位符,n是一个正整数,它们占据了传递给newCallable的参数的位置。n表示生成的可调用对象的参数的位置:如_1为newCallable的第1个参数,_2为newCallable的第2个参数,_3为newCallable的第3个参数,以此类推,_1/_2/_3…这些占位符都在一个叫placeholders的命名空间中。

#include<functional>usingnamespace placeholders;intSub(int a,int b){return a - b;}intmain(){// _1代表sub1的第一个参数,_2代表sub1的第二个参数。// bind内写成_2, _1的顺序,意味sub1的第二个参数会传给Sub的第一个参数a,sub1的第一个参数会传给Sub的第二个参数bauto sub1 =bind(Sub, _2, _1); cout <<Sub(1,2)<< endl; cout <<sub1(1,2)<< endl;return0;}
在这里插入图片描述


这是只改变参数顺序的一般用法。

bind还有最常用的改变参数个数用法,这个用法一般是为了绑死某些参数,使之为一个固定值,使用时就不需要再传参:

#include<functional>usingnamespace placeholders;intSub(int a,int b){return a - b;}intmain(){// _1代表sub2的第一个参数,100代表绑死Sub的第一个参数a,a的值固定为100了// a的值固定了,传参时就不需要传给a,sub2的第一个参数就会传给Sub的第二个参数bauto sub2 =bind(Sub,100, _1); cout <<Sub(1,2)<< endl; cout <<sub2(1);return0;}
在这里插入图片描述

再比如,刚才上面讲到function包装类成员函数时说到,使用包装后的对象时还需要传给this指针一个参数。有了bind就可以提前绑死这个参数,后续每次使用就不需要额外传了:

#include<functional>usingnamespace placeholders;classPlus{public:Plus(int n =10):_n(n){}doubleplusd(double a,double b){return(a + b)* _n;}private:int _n;};intmain(){ function<double(double,double)> f =bind(&Plus::plusd,Plus(), _1, _2); cout <<f(1,2)<< endl;return0;}
在这里插入图片描述

本篇完,感谢阅读。

Read more

Flutter 三方库 ethereum 鸿蒙分布式区块链数字资产上链钱包适配突破:接通 JSON-RPC 加密管线深入打通智能合约闭环实现高价值数字加密交互-适配鸿蒙 HarmonyOS ohos

Flutter 三方库 ethereum 鸿蒙分布式区块链数字资产上链钱包适配突破:接通 JSON-RPC 加密管线深入打通智能合约闭环实现高价值数字加密交互-适配鸿蒙 HarmonyOS ohos

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 ethereum 鸿蒙分布式区块链数字资产上链钱包适配突破:接通 JSON-RPC 加密管线深入打通智能合约闭环实现高价值数字加密交互无缝穿透 随着 Web3 技术与移动端的深度融合,支持区块链交互的应用日益增多。ethereum 库专注于以太坊(Ethereum)协议的底层通讯,为开发者提供了便捷的 Web3 集成方案。本文将详细介绍该库在 OpenHarmony 上的适配要点与实战指南。 前言 以太坊是目前最活跃的智能合约平台。在鸿蒙操作系统这个创新的万物智联生态中,支持以太坊交互可以为鸿蒙应用带来去中心化身份(DID)、数字资产(NFT)以及去中心化金融(DeFi)等前沿能力。本文将带你实现在鸿蒙端极速调起智能合约并查询链上数据。 一、原理解析 1.1 基础概念 ethereum 库封装了标准的以太坊 JSON-RPC 协议。在鸿蒙端,它利用 HTTP 请求与以太坊节点(

By Ne0inhk
庖丁解牛:深入拆解Linux静态库与动态库——从制作到使用的核心技巧讲解

庖丁解牛:深入拆解Linux静态库与动态库——从制作到使用的核心技巧讲解

🔥海棠蚀omo:个人主页                         ❄️个人专栏:《初识数据结构》,《C++:从入门到实践》,《Linux:从零基础到实践》                         ✨追光的人,终会光芒万丈 博主简介: 目录 一.什么是库? 二.静态库的制作与使用 2.1何为静态库? 2.2静态库的使用 2.3解决库文件使用过程中的问题 2.4静态库使用的延伸知识 三.动态库的制作与使用 3.1动态库的使用 3.2动态库使用的延伸知识 今天我们就要步入新的内容:关于库的制作与原理,这方面的知识想必一直是大家在学习中的痛点,今天我们就来好好聊聊它的知识。 一.什么是库? 在讲解后面的知识前我们先要弄明白到底什么是库? 简而言之,库是写好的现有的,成熟的,可以复⽤的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个⼈的代码都从零开始,因此库的存在意义⾮同寻常。 在我们日常写C语言代码时,所包含的<

By Ne0inhk
HarmonyOS 网络请求与数据持久化

HarmonyOS 网络请求与数据持久化

网罗开发(小红书、快手、视频号同名) 大家好,我是展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。 图书作者:《ESP32-C3 物联网工程开发实战》 图书作者:《SwiftUI 入门,进阶与实战》 超级个体:COC上海社区主理人 特约讲师:大学讲师,谷歌亚马逊分享嘉宾 科技博主:华为HDE/HDG 我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。

By Ne0inhk
Flutter 三方库 metalink_advanced_final 的鸿蒙化适配指南 - 在 OpenHarmony 打造极致、安全的 P2P 下载与资源分发底座

Flutter 三方库 metalink_advanced_final 的鸿蒙化适配指南 - 在 OpenHarmony 打造极致、安全的 P2P 下载与资源分发底座

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 metalink_advanced_final 的鸿蒙化适配指南 - 在 OpenHarmony 打造极致、安全的 P2P 下载与资源分发底座 在大数据传输、大型游戏资源更新以及分布式固件升级场景中,传统的单点 HTTP 下载往往面临带宽压力和校验失效的风险。metalink 协议(RFC 5854)通过整合多个源地址与强校验机制,提供了一套工业级的资源分发方案。metalink_advanced_final 库为 Flutter 开发者提供了该协议的终极解析与执行引擎。本文将深度解析如何在 OpenHarmony(鸿蒙)环境下,结合鸿蒙的并发架构,完美适配这一强大的下载工具。 前言 随着鸿蒙系统(HarmonyOS)跨终端特性的普及,应用在不同设备间流转时的资源同步速度成为了用户体验的“胜负手”。metalink_advanced_final

By Ne0inhk