C++之可调用对象、bind绑定器和function包装器
可调用对象
在C++中,可以像函数一样调用的有:普通函数、类的静态成员函数、仿函数、lambda函数、类的非静态成员函数、可被转换为函数的类的对象,统称可调用对象或函数对象。
可调用对象有类型,可以用指针存储它们的地址,可以被引用(类的成员函数除外)。
这里举几个例子
仿函数(本质是重载了()的类)
#include<iostream>
using namespace std;
struct Object
{void operator()(int age, string name){cout << "年龄:" << age << ",姓名:" << name << endl;}
};
int main()
{Object obj;obj(20, "小谢");Object& obj_r = obj; // 引用函数obj_r(19, "小赵");return 0;
}lambda函数
#include<iostream>
using namespace std;
int main()
{auto func = [](int age, string name){cout << "年龄:" << age << ",姓名:" << name << endl;};func(20, "小谢");auto& func_r = func;// 引用lambda对象。func_r(19, "小赵");return 0;
}类的非静态成员函数
类的非静态成员函数有地址,但是,只能通过类的对象才能调用它,所以,C++对它做了特别处理。
类的非静态成员函数只有指针类型,没有引用类型,不能引用。
#include<iostream>
using namespace std;
struct Object
{void show(int age, string name){cout << "年龄:" << age << ",姓名:" << name << endl;}
};
int main()
{Object obj;obj.show(20, "小谢");void(Object::*pobj)(int, string) = &Object::show;// 定义类的成员函数的指针。(obj.*pobj)(19, "小赵");using PFun = void(Object::*)(int, string);PFun p_show = &Object::show;(obj.*p_show)(18, "芜湖");return 0;
}在上面的例子中满足条件的这些可调用对象对应的类型被统称为可调用类型。C++ 中的可调用类型虽然具有比较统一的操作形式,但定义方式五花八门,这样在我们试图使用统一的方式保存,或者传递一个可调用对象时会十分繁琐。现在,C++11通过提供std::function 和 std::bind统一了可调用对象的各种操作。
包装器function
包含头文件:#include <functional>
std::function<返回值类型(参数类型列表)> diy_name = 可调用对象;
#include<iostream>
#include<functional>
using namespace std;
int add(int a, int b)
{cout << a << "+" << b << "=" << a + b << endl;return a + b;
}
class T
{
public:static int sub(int a, int b){cout << a << "*" << b << "=" << a * b << endl;return a * b;}
};
class T1
{
public:int operator()(int a, int b){cout << a << "-" << b << "=" << a - b << endl;return a - b;}
};
int main()
{//std::function<返回值类型(参数类型列表)> diy_name = 可调用对象;function<int(int, int)> f1 = add;f1(1, 2);function<int(int, int)> f2 = T::sub;f2(2, 3);T1 t;function<int(int, int)> f3 = t;f3(3, 4);return 0;
}通过测试代码可以得到结论:std::function 可以将可调用对象进行包装,得到一个统一的格式,包装完成得到的对象相当于一个函数指针,和函数指针的使用方式相同,通过包装器对象就可以完成对包装的函数的调用了。
作为回调函数使用
#include <iostream>
#include <functional>
using namespace std;
class A
{
public:// 构造函数参数是一个包装器对象A(const function<void()>& f) : callback(f){}void notify(){callback(); // 调用通过构造函数得到的函数指针}
private:function<void()> callback; //成员变量->包装器对象
};class B
{
public:void operator()(){cout << "!!!" << endl;}
};
int main(void)
{B b;A a(b);a.notify();return 0;
}
绑定器bind
std::bind()模板函数是一个通用的函数适配器(绑定器),它用一个可调用对象及其参数,生成一个新的可调用对象,以适应模板。
函数原型
template< class Fx, class... Args >function<> bind (Fx&& fx, Args&...args);
Fx:需要绑定的可调用对象
args:/*绑定参数列表,可以是左值、右值和参数占位符std::placeholders::_n,如果参数不是占位符,缺省为值传递,std:: ref(参数)则为引用传递。*/std::bind()返回std::function的对象。
std::bind()的本质是仿函数。
// 绑定非类成员函数/变量
auto f = std::bind(可调用对象地址, 绑定的参数/占位符);
// 绑定类成员函/变量
auto f = std::bind(类函数/成员地址, 类实例对象地址, 绑定的参数/占位符);
类成员函数需要绑定该类的this指针 。

#include<iostream>
#include<functional>
using namespace std;
struct Object
{void operator()(int age, string name){cout << "年龄:" << age << ",姓名:" << name << endl;}void show(int age, string name){cout << "年龄:" << age << ",姓名:" << name << endl;}};
int main()
{Object obj;function<void(int, string)> f1 = bind(Object(), placeholders::_1, placeholders::_2);f1(20, "小谢");auto func = [](int age, string name){cout << "年龄:" << age << ",姓名:" << name << endl;};function<void(int, string)> f2 = bind(func, placeholders::_1, placeholders::_2);f2(19, "小赵");// 类成员函数需要绑定该类的this指针 Object obj1;function<void(Object&, int, string)> f3 = bind(&Object::show, placeholders::_1, placeholders::_2, placeholders::_3);f3(obj1,17,"张三");//这里为了统一,将对象提前绑定function<void(int, string)> f4 = bind(&Object::show, obj1, placeholders::_1, placeholders::_2);f4(16, "李四");return 0;
}在用绑定器绑定类成员函数或者成员变量的时候需要将它们所属的实例对象一并传递到绑定器函数内部。
bind的应用
改变参数位置
例如函数需要一个int和string两个参数
auto f = bind(func, placeholders::_1, placeholders::_2);第一个参数为int,第二个为string,但是如果第一个想第一个传入string,第二个传入int
auto f = bind(func, placeholders::_2, placeholders::_1);改变参数个数
改变参数个数主要是为了统一,便于使用函数模板,例如上述例子的部分代码
Object obj1;
function<void(Object&, int, string)> f3
= bind(&Object::show, placeholders::_1, placeholders::_2, placeholders::_3);
f3(obj1,17,"张三");
//这里为了统一,将对象提前绑定
function<void(int, string)> f4 = bind(&Object::show, obj1, placeholders::_1, placeholders::_2);
f4(16, "李四");这里采取的是提前绑定,将对象提前绑定。
设置类成员函数为回调函数
在讲bind时上面已演示!!
相关文章:
C++之可调用对象、bind绑定器和function包装器
可调用对象在C中,可以像函数一样调用的有:普通函数、类的静态成员函数、仿函数、lambda函数、类的非静态成员函数、可被转换为函数的类的对象,统称可调用对象或函数对象。可调用对象有类型,可以用指针存储它们的地址,可…...
MongoDB--》文档查询的详细具体操作
目录 统计查询 分页列表查询 排序查询 正则的复杂条件查询 比较查询 包含查询 条件连接查询 统计查询 统计查询使用count()方法,其语法格式如下: db.collection.count(query,options) ParameterTypeDescriptionquerydocument查询选择条件optio…...
网络协议(六):网络层
网络协议系列文章 网络协议(一):基本概念、计算机之间的连接方式 网络协议(二):MAC地址、IP地址、子网掩码、子网和超网 网络协议(三):路由器原理及数据包传输过程 网络协议(四):网络分类、ISP、上网方式、公网私网、NAT 网络…...
热启动预示生态起航的Smart Finance,与深度赋能的SMART通证
2023年初加密市场的回暖,意味着各个赛道都将在新的一年里走向新的叙事。最近,我们看到GameFi赛道也在市场回暖的背景下,逐渐走出阴霾。从融资数据上看,1月获得融资的GameFi项目共12个,融资突破8000万美元,1…...
提分必练,中创教育PMP全真模拟题分享
湖南中创教育每日五题分享来啦,“日日行,不怕千万里;常常做,不怕千万事。”,每日五题我们练起来! 1、在系统测试期间,按已识别原因的类型或类别记录了失败测试的数量。项目经理首先需要从最大故…...
PID控制算法基础介绍
PID控制的概念 生活中的一些小电器,比如恒温热水器、平衡车,无人机的飞行姿态和飞行速度控制,自动驾驶等等,都有应用到 PID——PID 控制在自动控制原理中是一套比较经典的算法。 为什么需要 PID 控制器呢? 你一定用…...
Ajax 学习笔记
一、Ajax1.1 什么是AjaxAJAX Asynchronous JavaScript and XML(异步的JavaScript和XML)。Ajax是一种在无需加载整个网页的情况下,能够更新部分网页的技术,它不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术…...
力扣解法汇总1234. 替换子串得到平衡字符串
目录链接: 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目: https://github.com/September26/java-algorithms 原题链接:力扣 描述: 有一个只含有 Q, W, E, R 四种字符,且长度为 n 的字符串。 假如在该…...
C++关键字之const、inline、static
C 关键字总结 1.const const是 constant 的缩写,本意是不变的、不易改变的意思。在C中用来修饰内置类型变量,自定义对象,成员函数,返回值,函数参数使用如下: //修饰普通类型变量 const int a 7; int ba;…...
【成为架构师课程系列】怎样进行概念架构(Conceptual Architecture)?
目录 前言 什么是概念架构 概念架构阶段的3个步骤 初步设计 高层分割 分层式概念服务架构 Layer:逻辑层 Tier: 物理层 按通用性分层 技术堆叠 考虑非功能需求 【禅与计算机程序设计艺术:更多阅读】 前言 胜兵先胜而后求战,败兵先站而后求胜。…...
PostgreSQL的下载安装教程(macOS、Windows)
postgresql是GIS服务端几乎不可避免要打交道的数据库。因为mysql的空间扩展真是不尽人意。所以想要学会GIS服务端知识,postgresql(下文简称pg)你是必须要会的。 首先要知道,pg是一个空间数据库,和普通数据库不同的是pg支持空间数据的存储与操作。这里所谓的空间数据一般指…...
98年的确实卷,公司新来的卷王,我们这帮老油条真干不过.....
都说00后躺平了,但是有一说一,该卷的还是卷。这不,前段时间我们公司来了个00后,工作没两年,跳槽到我们公司起薪18K,都快接近我了。后来才知道人家是个卷王,从早干到晚就差搬张床到工位睡觉了。 …...
软件架构知识2-系统复杂度
架构设计的真正目的:是为了解决软件系统复杂度带来的问题,一个解决方案。 系统复杂度,如何入手: 1、通过熟悉和理解需求,识别系统复杂性所在的地方,然后针对这些复杂点进行架构设计。 2、架构设计并不是要…...
JavaSE学习day4_02 数组(超级重点)
3.数组 3.1什么是数组 数组就是存储数据长度固定的容器,存储多个数据的数据类型要一致。 3.2数组定义格式 3.2.1第一种(常用) 数据类型[] 数组名 示例: int[] arr; double[] arr; char[] arr; 3.2.2第二种(在…...
Theano教程:Python的内存管理
在写大型程序时候的一大挑战是如何保证最少的内存使用率。但是在Python中的内存管理是比较简单的。Python显示分配内存,使用引用计数系统管理对象,当指向某一个对象的引用数变为 0 的时候,该对象所占的内存就会被释放。理论上听起来很不错&am…...
Linux | Liunx安装Tomcat(Ubuntu版)
目录 一、下载并上传Tomcat压缩包到Ubuntu 1.1 下载并解压 1.2 执行 startup.sh 文件 二、验证Tomcat启动是否成功 2.1 查看启动日志 2.2 查看启动进程 三、Windows访问 Tomcat 服务 四、停止 Tomcat 服务 Tomcat是一款Web服务器,开发Web项目基本上都会用到…...
缓冲区浅析
缓冲区 程序运行输入数据时,从键盘的输入先存储到缓冲区,只有当缓冲区满或者输入回车时程序才会真正地从缓冲区读入数据 int main() {int a, b;cin >> a >> b;return 0; }in: 1 2\n 例如这里输入空格时程序没有输出,而是将空格…...
Day888.MySQL是怎么保证主备一致的 -MySQL实战
MySQL是怎么保证主备一致的 Hi,我是阿昌,今天学习记录的是关于MySQL是怎么保证主备一致的内容。 MySQL 能够成为现下最流行的开源数据库,binlog 功不可没。 在最开始,MySQL 是以容易学习和方便的高可用架构,被开发人…...
互联网舆情监测系统的发展阶段,TOOM互联网舆情监测系统有哪些?
互联网舆情监测系统是一种利用计算机技术对互联网上的大量信息进行实时监测、分析和评估的工具,旨在了解公众对某一事件、话题或品牌等的态度、情感倾向和影响力等。通过对社交媒体、论坛、新闻媒体等多个渠道的数据采集和处理,系统能够实现舆情事件的追…...
GIT命令操作大全
文章目录一、前言二、工作模块2.1 Workspace:工作区2.2 Index / Stage:暂存区2.3 Repository:本地仓库2.4Remote:远程仓库三、GIT基本配置四、GIT项目代码管理4.1 初始化git仓库4.2 提交到暂存区(stage)4.3 将暂存区的文件恢复到工…...
ABYSSAL VISION(Flux.1-Dev)风格化研究:模拟Typora等工具的极简文档配图
ABYSSAL VISION(Flux.1-Dev)风格化研究:模拟Typora等工具的极简文档配图 不知道你有没有过这样的体验:写技术文档或者博客的时候,文字部分洋洋洒洒,逻辑清晰,但一到需要配图说明的地方就卡壳了…...
利用快马ai快速生成c语言语法学习原型,直观掌握编程基础
今天想和大家分享一个特别实用的C语言学习小技巧。作为一个编程新手,我最近发现用InsCode(快马)平台可以快速搭建C语言学习原型,把抽象的概念变成看得见、能运行的代码,学习效果特别好。 为什么要用原型学习法 刚开始学C语言时,最…...
douyin-downloader:抖音视频批量下载解决方案
douyin-downloader:抖音视频批量下载解决方案 【免费下载链接】douyin-downloader 项目地址: https://gitcode.com/GitHub_Trending/do/douyin-downloader 在数字内容爆炸的时代,视频资源的高效管理已成为内容创作者、教育工作者和社交媒体运营者…...
用SUSE Linux+PHPStudy快速搭建FusionAccess测试环境(避坑指南)
用SUSE LinuxPHPStudy快速搭建FusionAccess测试环境(避坑指南) 在数字化转型浪潮中,桌面云技术正成为企业IT架构革新的关键推手。FusionAccess作为业界领先的虚拟桌面解决方案,其灵活性和高效性备受开发者青睐。然而,传…...
FlowState Lab少样本学习效果:仅用10条数据生成特定波动模式
FlowState Lab少样本学习效果:仅用10条数据生成特定波动模式 1. 引言:当数据稀缺遇上智能生成 想象一下这样的场景:你手里只有10条设备振动波形数据,却需要分析上千种可能的故障模式。传统方法可能需要收集数月甚至数年的运行数…...
卡尔曼滤波+LQR实战:用Python手写一个LQG控制器(附Jupyter Notebook)
卡尔曼滤波LQR实战:用Python手写一个LQG控制器(附Jupyter Notebook) 在机器人控制和自动化系统设计中,LQG(Linear Quadratic Gaussian)控制是一种经典且强大的控制策略。它巧妙地将卡尔曼滤波的状态估计能力…...
s2-pro语音合成教程:支持数字/单位/英文缩写智能朗读技巧
s2-pro语音合成教程:支持数字/单位/英文缩写智能朗读技巧 1. 快速了解s2-pro语音合成 s2-pro是Fish Audio开源的专业级语音合成模型镜像,它能将文本转换为自然流畅的语音。这个工具特别适合需要语音播报、有声读物制作、视频配音等场景的用户。 与普通…...
RWKV7-1.5B-G1A入门实战:手把手教你写文案、做总结、玩对话
RWKV7-1.5B-G1A入门实战:手把手教你写文案、做总结、玩对话 1. 认识RWKV7-1.5B-G1A RWKV7-1.5B-G1A是一个基于RWKV-7架构的多语言文本生成模型,特别适合处理基础问答、文案续写、简短总结和轻量中文对话任务。这个1.5B参数的模型在保持良好生成质量的同…...
文艺复兴,什么是XSS,常见形式(二)
前言 本文将继续介绍XSS的常见形状,依赖于portswigger提供的免费Lab环境,将重点介绍关于使用脚本来进行表单XSS验证以及针对标签的模糊测试。 Lab: Stored DOM XSS 这是一个存储型的DOM类的XSS,具体的是当你将内容提交到评论区,…...
3分钟轻松获取无水印抖音视频:DouYinBot全能解析工具使用指南
3分钟轻松获取无水印抖音视频:DouYinBot全能解析工具使用指南 【免费下载链接】DouYinBot 抖音无水印下载 项目地址: https://gitcode.com/gh_mirrors/do/DouYinBot 在短视频创作的浪潮中,每个创作者都曾遇到这样的困扰:精心挑选的抖音…...
