C++11 function包装器

这篇具有很好参考价值的文章主要介绍了C++11 function包装器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

在C++中,有三种可调用对象:函数指针,仿函数,lambda表达式。
三者有相似的作用和效果,但使用形式有很大的差异。
为了进行统一,C++11引进了function包装器

C++11 function包装器,C++学习笔记,c++,开发语言

一. function的使用

首先,要想使用function,需要包含functional这个头文件

C++11 function包装器,C++学习笔记,c++,开发语言

function包装器本质是一个类模板

std::function在头文件<functional>
// 类模板原型如下
template <class T> function;     // undefined
template <class Ret, class... Args>
class function<Ret(Args...)>;

模板参数说明:
Ret: 被调用函数的返回类型
Args…:被调用函数的形参

以往,如果要实现一个加法,函数指针,仿函数,lambda表达式的实现方式如下:

#include<iostream>
#include<functional>

using namespace std;

//函数
int func(int a, int b)
{
	cout << "int func(int a, int b)" << endl;
	return a + b;
}
//仿函数
class Func
{
public:
	int operator()(int a, int b)
	{
		cout << "int operator()(int a, int b)" << endl;
		return a + b;
	}
};


int main()
{
	//函数指针
	int(*fp)(int, int) = func;
	fp(1, 3);
	
	//仿函数
	Func ff;
	ff(1, 3);
	
	//lambda表达式
	auto fl=[](int a,int b)->int
	{
		cout << "[](int a,int b)->int{}" << endl;
		return a + b;
	};
	fl(1, 3);
	
	return 0;
}

虽然都可以完成需求,但使用方式差别太大,而function就可以将三者统一包装起来

C++11 function包装器,C++学习笔记,c++,开发语言

可以看到,function包装器统一封装了三种可调用对象,且最终类型相同,这就是包装器的使用
< >中,第一个int是返回值类型,( )中是参数类型

functiona的使用还有如下场景:

map<string, function<int(int, int)>>funcMap;
funcMap["函数指针"] = fp;
funcMap["仿函数"] = Func();
funcMap["lambda"] = [](int a, int b)->int
{
	cout << "[](int a,int b)->int{}" << endl;
	return a + b;
};

二. function对成员函数的包装

除了以上的三种可调用对象,成员函数同样可以使用function包装,不过使用有些不同

首先,对于静态成员函数,function的包装没有什么差别

class Func
{
public:
	//静态成员函数
	int static staFunc(int a)
	{
		cout << "int static staFunc(int a)" << endl;
		return a;
	}
	//普通成员函数
	int norFunc(int a)
	{
		cout << "int norFunc(int a)" << endl;
		return a;
	}
};

int main()
{
	//静态成员函数
	//function<int(int)>f1 = Func::staFunc;//可以不需要&
	function<int(int)>f1 = &Func::staFunc;//需要指类域
	
	return 0;
}

对于成员函数,包装器要求&,不过静态成员函数可以不使用&
但是对于普通成员函数,即使加了&,也不行

C++11 function包装器,C++学习笔记,c++,开发语言

因为普通的成员函数其实有一个隐藏的参数——this指针
所以如果要包装普通成员函数,function的类模板还需要加上类对象

//普通成员函数
function<int(Func,int)>f2 = &Func::norFunc;
f2(Func(),10);//使用

PS:类对象不是对应this指针,而是function调用成员函数时,需要通过类对象调用成员函数
其实也可以传Func*,function就是通过类对象指针调用成员函数
但是这样就无法使用匿名对象,因为匿名对象是右值,不能取地址

function<int(Func*,int)>f2 = &Func::norFunc;
f2(&Func(),10);//错误

三. bind绑定

functional头文件中,还有一个比较实用的函数适配器——bind

bind是一个函数模板,接收一个可调用对象,生成一个新的可调用对象来适应原对象的参数列表
一般而言,我们可以使用bind把一个原本需要传N个参数的函数fn,通过绑定一些参数,返回一个需要传M个(M可以大于N,但这么做没什么意义)参数的新函数。
同时,使用bind函数还可以实现参数顺序的调整等操作

C++11 function包装器,C++学习笔记,c++,开发语言

1. 调整参数顺序

通过bind绑定可以调整参数顺序
比如:

void Func(int a, int b)
{
	cout << a << " ";
	cout << b << endl;
}

如果我们要调整参数a和b的顺序

bind的使用如下:

int main()
{
	function<void(int, int)>f1 = Func;
	f1(10, 20);

	auto f2 = bind(f1, placeholders::_2, placeholders::_1);
	f2(10, 20);

	return 0;
}

placeholders是头文件functional中的一个命名空间

C++11 function包装器,C++学习笔记,c++,开发语言

placeholders::_1和placeholders::_2都是占位符
function本质是仿函数,而bind是根据占位符,和提供的可调用对象重新生成仿函数。
因为bind是函数模板,参数是万能引用,所以函数指针,仿函数,lambda同样可以调整

auto f3 = bind(Func, placeholders::_2, placeholders::_1);

返回的是一个_Binder类
C++11 function包装器,C++学习笔记,c++,开发语言
内部包装了可调用对象,并且根据提供的占位符调整参数顺序

2. 调整参数个数

在使用function包装成员函数时,因为有this指针的存在,使得代码编写较为复杂,而bind则可以提前绑死参数

使用如下:

class Func
{
public:
	int norFunc(int a)
	{
		cout << "int norFunc(int a)" << endl;
		return a;
	}
};

int main()
{
	function<int(Func,int)>f1 = &Func::norFunc;
	f1(Func(), 5);
	//使用bind提前绑定Func对象
	auto f2 = bind(&Func::norFunc, Func(), placeholders::_1);
	f2(5);
}

提前绑死Func对象,就不需要再调用时,显式传Func对象

结束语

感谢你的阅读

如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。
C++11 function包装器,C++学习笔记,c++,开发语言文章来源地址https://www.toymoban.com/news/detail-549243.html

到了这里,关于C++11 function包装器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 单例宏及函数包装器function的使用

    1)单例模式中,用单例宏定义,测试代码如下: 2)std::bind函数适配器及std::function函数包装器的配合使用,测试代码如下: 利用了回调函数的使用方法: 3)终于明白了std::function的设计为回调函数的使用方法,测试代码如下: 4)再次理解std::function和std::bind绑定器的结合使

    2024年02月09日
    浏览(45)
  • C语言学习笔记 vscode使用外部console-11

    在默认情况下,我们运行C语言程序都是在vscode终端的,在小程序运行时这个是没有问题的,但是当程序变得复杂它就不好用了,这时我们可以将这个终端设置为外部console,这样方便处理更多、更复杂的程序。 1.点击左角的文件夹下的.vscode目录下的lauch.json文件 2.在打开的文件

    2024年02月13日
    浏览(36)
  • 微信小程序开发学习笔记——2.11navigator页面链接导航

    跟着b站up主“咸虾米_”学习微信小程序开发中,把学习记录存到这方便后续查找。 课程连接: https://www.bilibili.com/video/BV19G4y1K74d?p=14 https://developers.weixin.qq.com/miniprogram/dev/component/navigator.html 属性之一          navigate可以记录上一个缓存页,点击左上角返回按钮可以跳转回

    2024年02月22日
    浏览(45)
  • 【鸿蒙系统学习笔记】ArkTS开发语言

    ArkTS 是 HarmonyOS 优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript(简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集。 ArkTS的基本组成,资料来自官网:文档中心 说明: ①装饰器:用来装饰类结构、方法、变量 @Component表示自定义组件,@Entry表示该

    2024年02月20日
    浏览(40)
  • 【鸿蒙系统学习笔记】TypeScript开发语言

    HarmonyOS 应用的主要开发语言是 ArkTS,它由 TypeScript(简称TS)扩展而来,在继承TypeScript语法的基础上进行了一系列优化,使开发者能够以更简洁、更自然的方式开发应用。值得注意的是,TypeScript 本身也是由另一门语言 JavaScript 扩展而来。因此三者的关系如下图所示 2.1.1、线

    2024年02月19日
    浏览(42)
  • 强化学习的数学原理学习笔记 - 值函数近似(Value Function Approximation)

    本系列文章介绍强化学习基础知识与经典算法原理,大部分内容来自西湖大学赵世钰老师的强化学习的数学原理课程(参考资料1),并参考了部分参考资料2、3的内容进行补充。 系列博文索引: 强化学习的数学原理学习笔记 - RL基础知识 强化学习的数学原理学习笔记 - 基于

    2024年01月22日
    浏览(42)
  • 【C++】C++11 包装器

    👀 樊梓慕: 个人主页  🎥 个人专栏: 《C语言》 《数据结构》 《蓝桥杯试题》 《LeetCode刷题笔记》 《实训项目》 《C++》 《Linux》 《算法》 🌝 每一个不曾起舞的日子,都是对生命的辜负 目录 前言 function包装器 function包装器概述 function包装器使用 function包装器的实际应

    2024年04月26日
    浏览(28)
  • 【C++11】 包装器 | bind

    function包装器 也被叫做 适配器 C++11中function本质是 类模板, 也是一个包装器 意义在于 对可调用对象类型进行封装再适配 可调用对象:函数指针 / lambda / 仿函数 需要包含 头文件 functional 模板参数 Ret : 被调用函数的返回类型 …Args作为参数包,这个参数包中包含0到任意个模

    2024年02月12日
    浏览(38)
  • 【C++】C++11 ~ 包装器解析

    (꒪ꇴ꒪(꒪ꇴ꒪ )🐣,我是 Scort 目前状态:大三非科班啃C++中 🌍博客主页:张小姐的猫~江湖背景 快上车🚘,握好方向盘跟我有一起打天下嘞! 送给自己的一句鸡汤🤔: 🔥真正的大师永远怀着一颗学徒的心 作者水平很有限,如果发现错误,可在评论区指正,感谢🙏 🎉🎉

    2024年02月01日
    浏览(34)
  • Flink|《Flink 官方文档 - DataStream API - 用户自定义 Functions》学习笔记 + 源码分析

    学习文档:Flink 官方文档 - DataStream API - 用户自定义 Functions 学习笔记如下: 用户可以通过实现接口来完成自定义 Functions。 实现接口并使用的样例: 使用匿名类实现的样例: 使用 Lambda 表达式实现(Java 8)样例: 所有的 Flink 函数类都有其 Rich 版本,在 Rick function 中,可以获

    2024年01月18日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包