C++_包装器

       

目录

1、包装器的用法

2、包装器的类型 

3、包装器的作用 

4、包装成员函数

5、bind(绑定)

5.1 bind的用法         

5.2 bind减少参数个数 

结语


前言:

        C++11的包装器,总称为function包装器,而包装器又称适配器,顾名思义包装器主要是用于包装函数的,实际上是将函数指针、仿函数类、lambda函数进行了又一层的封装。 

1、包装器的用法

       包装器的具体结构如下:

使用包装器需包头文件:<functional>

// 类模板原型如下
template <class Ret, class... Args>
class function<Ret(Args...)>;

模板参数说明:
Ret: 被调用函数的返回类型
Args…:可变参数包,表示被调用函数的形参可以有多个

        包装器测试代码如下:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
#include<functional>
using namespace std;

int f(int a, int b)
{
	cout << "int f(int a, int b)" << endl;
	return a + b;
}

int main()
{
	function<int(int, int)> f1 = f;//包装函数f

	cout << f1(1, 2) << endl;//使用包装器调用函数f
	return 0;
}

        运行结果:

        从结果可以看到,若要使用包装器封装函数,则包装器的返回类型和参数必须和该函数一致,示意图如下:

        并且包装器仅仅只是封装了函数f,并且生成一个包装器对象,用包装器对象去调用包装的函数时,还是会去调用函数f的本体。 

2、包装器的类型 

        函数指针,lambda函数、仿函数类这三种函数本身是不能够直接进行赋值操作的,因为他们三个各有各的类型,然而经过包装器包装后,产生的三个包装器对象是可以直接进行相互赋值操作的。

        示例代码如下:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
#include<functional>
using namespace std;

int f(int a, int b)
{
	cout << "int f(int a, int b)" << endl;
	return a + b;
}
struct Functor
{
public:
	int operator() (int a, int b)
	{
		cout << "int operator() (int a, int b)" << endl;
		return a + b;
	}
};

int main()
{
	function<int(int, int)> f1 = f;
	function<int(int, int)> f2 = Functor();

	f1 = f2;//f2赋值给f1,则f1调用的是f2的函数,即Functor
	cout << f1(1, 2) << endl<<endl;
	cout << f2(1, 2) << endl;
	return 0;
}

        运行结果:

3、包装器的作用 

         在一些特殊的场景下,比如一个容器要接收函数指针,lambda函数、仿函数类,则该容器的类型晦涩难写,比如函数指针的类型:void(*ptr)(),写起来比较麻烦,更不用说lambda的类型了,就算取到了他们的类型,写出来的代码也属于高耦合的代码,即该容器只能接收三者之一的数据类型。

        而包装器可以实现以上的效果,并且写出来的代码属于低耦合的代码,即以上三种类型的数据都可以写进容器里,具体示例如下:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
#include<functional>
#include<map>
using namespace std;

int f(int a, int b)
{
	cout << "int f(int a, int b)" << endl;
	return a + b;
}
struct Functor
{
public:
	int operator() (int a, int b)
	{
		cout << "int operator() (int a, int b)" << endl;
		return a + b;
	}
};

int main()
{
	map < string, function<int(int, int)>> m1;//参数1为string,参数2为包装器

	//map的[] 进行插入元素,并返回第二个参数的引用
	m1["函数指针"] = f;
	m1["仿函数类"] = Functor();
	m1["lambda"] = [](int x, int y)->int
	{
		cout << "[](int x, int y)->int" << endl;
		return x + y;
	};

	cout << m1["函数指针"](1, 2) << endl << endl;
	cout << m1["仿函数类"](1, 2) << endl << endl;
	cout << m1["lambda"](1, 2) << endl;
	return 0;
}

        运行结果:

4、包装成员函数

        用包装器包装成员函数时需要考虑该成员函数是否有this指针,因为普通成员函数含this指针,而静态成员函数不含this指针,若函数中含this指针,则包装器的第一个参数一定是this指针。

        示例代码如下:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
#include<functional>
using namespace std;

class Wrapper
{
public:
	static int Wrapperi(int a, int b)//静态成员函数无this指针
	{
		return a + b;
	}
	int Wrapperd(int a, int b)
	{
		return a + b + res;
	}
private:
	int res = 2;
};

int main()
{
	function<int(int, int)> f1 = Wrapper::Wrapperi;

	//Wrapperd含this指针,因此要包装器的参数要多写一个this的类型
	function<int(Wrapper, int, int)> f2 = &Wrapper::Wrapperd;//此处要加取地址符

	cout << f1(2, 3) << endl;
	cout << f2(Wrapper(), 2, 3) << endl;

	return 0;
}

         运行结果:

        包装带this指针的另一种写法:

5、bind(绑定)

        bind的格式:

auto newTarget = bind(target,arg_list);
//target是一个函数对象,也可以是指向函数的指针
//arg_list是调整之后的参数列表
//newTarget也是一个函数对象

        bind也是一种函数适配器,他接收一个函数对象,并且对该函数的参数列表进行调整,如形参的顺序、形参的个数,最后返回一个函数对象,该对象可以调用调整之后的函数(即调用newTarget时,实际上是以arg_list为形参列表去调用target),可用包装器接收该newTarget。

5.1 bind的用法         

        测试bind的代码如下:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
#include<functional>
using namespace std;

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

int main()
{
	Wrapperi(2, 3);
	//将形参顺序倒置
	//placeholders表示占位符,placeholders::_2表示Wrapperi的第二个参数现在成了f1的第一个参数
	function<void(int, int)> f1 = bind(Wrapperi, placeholders::_2, placeholders::_1);

	//直接传参的写法
	auto f2 = bind(Wrapperi,20,10);//直接把20和10当作f2的形参

	f1(2, 3);//同样的调用顺序,结果实参2给到的是Wrapperi的形参b
	f2();
	
	return 0;
}

         运行结果:

         占位符用法的具体示意图如下:

5.2 bind减少参数个数 

         bind可以减少函数对象的参数个数,比如某函数有3个参数,因此调用该函数时需要传3个实参,但是bind可以将该函数减少为2个参数后给到一个新的函数对象,并且新函数对象调用该函数时不需要传3个实参。

        示例代码如下:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
#include<functional>
using namespace std;

class Sub
{
public:
	int sub(int a, int b)
	{
		return a - b;
	}
};
int main()
{
	//没有调整参数的调用方式
	std::function<int(Sub,int, int)> func2 = &Sub::sub;
	cout << func2(Sub(), 6, 3) << endl;

	//使用bind进行参数调整后的调用方式,调用包装器对象从3个参数变成了2个
	Sub s;
	std::function<int(int, int)> func3 = 
		std::bind(&Sub::sub,s,placeholders::_1, placeholders::_2);
	cout << func3(10, 8) << endl;
}

        运行结果:

        从结果可以发现,bind之所以可以减少参数是因为在bind中已经将该参数显示调用了,所以新函数对象才可以不用再次显示调用该参数。注意:并且func3(包装器)类型的形参个数要和bind减少参数之后的形参个数相匹配

结语

        以上就是关于包装器和bind的讲解,包装器的作用就是为了能够让程序员更好的显示表示函数对象的类型,而bind则是能够让一些函数对象能够相互的兼容,比如A函数对象比B函数对象的形参多一个,其余的参数都一样,为了能够让A和B的类型相等,可以使用bind让A的形参减少一个,这样他们就可以兼容了,比如下面场景:

        最后希望本文可以给你带来更多的收获,如果本文对你起到了帮助,希望可以动动小指头帮忙点赞👍+关注😎+收藏👌!如果有遗漏或者有误的地方欢迎大家在评论区补充,谢谢大家!! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/450718.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

模块化机房的成本效益分析

在当今日益数字化的商业环境中&#xff0c;数据中心的建设和运营成本成为企业关注的重点。模块化机房以其独特的优势&#xff0c;不仅满足了快速部署和高效能的需求&#xff0c;还显著降低了总体成本。本文将深入探讨模块化机房在不同方面带来的成本效益。 1.预制模块化设计 …

如何解决由触发器导致 MySQL 内存溢出?

由触发器导致得 OOM 案例分析过程和解决方式。 作者&#xff1a;龚唐杰&#xff0c;爱可生 DBA 团队成员&#xff0c;主要负责 MySQL 技术支持&#xff0c;擅长 MySQL、PG、国产数据库。 爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使用&#xff0c;转载请联系小编…

如何用 RAG 技术玩转文档问答?Milvus × 网易有道 QAnything 为你揭秘!

过去一年&#xff0c;RAG 在技术层面发展迅速&#xff0c;为向量数据库赛道添了一把火。RAG 和向量数据库的结合&#xff0c;能够有效解决幻觉、时效性差、专业领域知识不足等阻碍大模型应用的核心问题。 不久前&#xff0c;网易有道开源了自研的 RAG 引擎 QAnything。用户的任…

如何下载安装chromium浏览器

下载安装chromium浏览器去这个网站下载&#xff1a; CNPM Binaries Mirror 参考链接&#xff1a;手写 Puppeteer&#xff1a;自动下载 Chromium - 知乎

渲染农场:大规模渲染任务的高效处理方式

在当今的数字内容创作领域&#xff0c;渲染农场是处理大规模渲染任务的关键技术&#xff0c;它利用多台计算机的集群来分担复杂的渲染工作&#xff0c;大大提高了效率和速度。这篇文章将深入探讨渲染农场的工作原理、技术架构&#xff0c;以及如何根据需求选择合适的渲染农场。…

Vmware 点进centos不显示鼠标

今天安装了Vmward16 安装后在里面安装了centos7&#xff0c;但进入centos7 时没显示鼠标&#xff0c;但有点击效果。 设置了右上角的 编辑->首选项 -输入-》单击鼠标时抓取键盘和鼠标输入然后重启下vmware&#xff0c;但鼠标还是不显示 后面我的电脑重启了&#xff0c;然后…

【数学】【网格】【状态压缩】782 变为棋盘

作者推荐 视频算法专题 本文涉及知识点 数学 网格 状态压缩 LeetCode:782 变为棋盘 一个 n x n 的二维网络 board 仅由 0 和 1 组成 。每次移动&#xff0c;你能任意交换两列或是两行的位置。 返回 将这个矩阵变为 “棋盘” 所需的最小移动次数 。如果不存在可行的变换&am…

小区水电智能化系统

随着科技的进步&#xff0c;我们的生活变得越来越智能化&#xff0c;而小区水电智能化系统正是这一趋势的典范。这个系统不仅仅是一种便利&#xff0c;更是未来智慧生活的关键组成部分。让我们一起来了解一下它的奥秘吧! 让我们来看看小区水电智能化系统的核心&#xff1a;智能…

【Spring】idea连接mysql数据库

1 MySQL安装 下载地址&#xff1a;https://dev.mysql.com/downloads/installer/ 安装server only选项&#xff0c;之后的可以选择默认安装选项 2 MySQL登录并创建数据 -- 创建数据库 create databases spring_db; use spring_db; -- 创建表 create table users (id INT AUTO…

现货黄金交易网上有用的交易技巧

在不同的现货黄金交易网上&#xff0c;经常有投资者分享交易技巧。由于在网上发文没什么限制&#xff0c;所以这些交易技巧都是泥沙俱下&#xff0c;质量良莠不齐。不过也有一些是有用的&#xff0c;下面我们就来介绍一下现货黄金交易网上那些有用的交易技巧。 培养防守意识。什…

DataFunSummit 2023因果推断在线峰会:解码数据与因果,引领智能决策新篇章(附大会核心PPT下载)

在数据驱动的时代&#xff0c;因果推断作为数据科学领域的重要分支&#xff0c;正日益受到业界的广泛关注。DataFunSummit 2023年因果推断在线峰会&#xff0c;汇聚了国内外顶尖的因果推断领域专家、学者及业界精英&#xff0c;共同探讨因果推断的最新进展、应用与挑战。本文将…

滑动窗口的概念,糊涂窗口综合征,nagle算法

目录 1.流量控制 2.滑动窗口 3.思考问题 1.流量控制 一般来说,我们总是希望数据传输得更快一些,但如果发送方把数据发送得过快,接收方就可能来不及接收,这就会造成数据的丢失.所谓流量控制(flow control)就是发送方的发送速率不要太快,要让接收方来得及接收. 2.滑动窗口 T…

因为manifest.json文件引起的 android-chrome-192x192.png 404 (Not Found)

H5项目打包之后&#xff0c;总是有这个报错&#xff0c;有时候还有别的icon也找不见 一通调查之后&#xff0c;发现是因为引入了一个vue插件 这个插件引入之后&#xff0c;webpack打包的时候就会自动在dist文件夹中产生一个manifest.json文件这个文件里面主要就是一些icon地址的…

el-select 选项文字超长解决方案

先看现象 省略号显示 <el-selectv-model"configs.domain.secondLevel"style"width: 100%"filterableallow-createdefault-first-optionplaceholder"请输入二级网段名称&#xff0c;例如&#xff1a;广州研发中心/研发网"focus"setOpti…

#QT(本地音乐播放器)

1.IDE&#xff1a;QTCreator 2.实验&#xff1a;之前做的音乐播放器只做了一个界面&#xff0c;是因为跟的课程发现到后面需要付费&#xff0c;并且WINGW6.2.0运行QMediaPlayer时无法运行&#xff0c;会崩溃&#xff0c;现在退一步用WINGW5.12.2做一个本地音乐播放器 3.记录&am…

漏洞挖掘 | 没有弱口令的挖掘思路

没有弱口令怎么挖&#xff1f;依稀记得有一个很老的思路叫做禁用js可以跳转后台&#xff0c;奈何学习两年半到现在从未发现一个这种漏洞。 不过&#xff0c;虽然不能直接搞到未授权后台登录&#xff0c;但是站有站的设计&#xff0c;小白有小白的打法&#xff01; 访问某URL&am…

web开发——前端html、css、JavaScript学习总结(持续更新中.......)

目录模版 1 html:结构标签/属性文本标记: mark文本设置:删除线del / 下划线ins/ 加粗b / 强调的文本em / 重要的文本 strong超链接: a联系信息: addressdiv 定义文档中的分区或节: div行元素:spanhtml结构: main / section / articlenav表格:table html中各种标签/属性的英文扩…

ubuntu下vscode+STM32CubeMX+openocd+stlinkv2搭建STM32开发调试下载环境

1、换源 清华源 # 默认注释了源码镜像以提高 apt update 速度&#xff0c;如有需要可自行取消注释 deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy main restricted universe multiverse # deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy main restr…

Flink K8S Operator 离线安装

一 推送镜像 docker pull quay.io/jetstack/cert-manager-cainjector:v1.8.2 docker tag quay.io/jetstack/cert-manager-cainjector:v1.8.2 10.177.85.101:8000/flink/cert-manager-cainjector:v1.8.2 docker push 10.177.85.101:8000/flink/cert-manager-cainjector:v1.8.2d…

大预言模型——ChatGPT,Claude3、Sora、等技术

原文链接&#xff1a;大预言模型——ChatGPT,Claude3、Sora、等技术https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247596849&idx3&sn111d68286f9752008bca95a5ec575bb3&chksmfa823ad6cdf5b3c0c446eceb5cf29cccc3161d746bdd9f26cc060f78c359ec3e2a8f35…