C++ 函数封装与绑定

STL标准库中提供了一些函数包装的模板

它们可以对函数或者可调用的对象进行包装,方便在其他函数中调用

std::function

std::function是一个通用的多态函数封装器

它将一个可调用的对象,比如函数指针、函数对象、lambda函数等进行封装,方便在后续的代码中调用

std::function的定义:
复制代码
template<class R,class... Args>
class function<R<Args...>>;

// R<Args...> 这种定义方式是类模板的部分特化,可以将它拆成两个部分
//R 是函数返回类型
//Args是函数参数类型,...说明Args是一个可变模板参数,代表模板可以接受任意多个参数
std::function使用:

定义函数封装器对象

复制代码
function<R<Args...>> fname = target;

#include<iostream>
#include<functional>

double multiply(double a,double b)
{
	return a+b;
};

int main()
{
	std::function<double(double,double)> func1 = multiply;
	std::cout<< func1(4,5) <<std::endl;
	return 0;
}
封装类成员函数

在封装类成员函数时,第一个参数要传入类引用

复制代码
class Calc
{
public:
	Calc(int Inbase):base(Inbase){	}
	double multiplay(double a,double b){ return a * b; }
	double add(double a,double b){ return a + b; }
	
	int base;
};

int main()
{
	Calc c(123);
	
	//第一个参数要传入类引用
	std::function<double(Calc&,double,double)> Mfunc = &Calc::multiplay;
	std::cout<< Mfunc(c,4,5) <<std::endl;
	//也可以封装成员变量
	std::function<int(Calc&)> Mbase = &Calc::base;
	std::cout<< Mbase(c) <<std::endl;
	
	return 0;
}
类型擦除

std::function只需定义一个函数封装器对象,就可以接收函数指针、函数对象、lambda函数,只要它们的函数签名相同

复制代码
#include<iostream>
#include<functional>
#include<map>

double add(double a,double b)
{
	return a+b;
}
class Substract
{
public:
	double operator()(double a,double b){ return a - b; }
};

int main()
{
	std::map<char,std::function<double(double,double)>> calculator{
		{ '+',add},
		{ '-',Substract()},
		{ '*',[](double a,double b)->double {return  a*b;}}
	};
	std::cout<< calculator['+'](1.1,2)<<std::endl;
	std::cout<< calculator['-'](5,3)<<std::endl;
	std::cout<< calculator['*'](4,6)<<std::endl;
	return 0;
}

std::mem_fn

它主要是封装类成员函数,传入成员函数的地址,返回包装器

复制代码
#include<iostream>
#include<functional>


class Calc
{
public:
	double multiplay(double a,double b){ return a * b; }
	double operator+=(double a){ return a + 10; }
};

int main()
{
	Calc c;
	auto Mfunc1 = std::mem_fn(&Calc::multiplay);
	std::cout<<Mfunc1(c,1,2)<<std::endl;

	//可以封装运算符重载的函数
	auto Mfunc2 = std::mem_fn(&Calc::operator+=);
	std::cout<<Mfunc2(c,4)<<std::endl;
	return 0;
}

std::bind

std::bind 可以将函数包装成函数对象(仿函数)

绑定参数
复制代码
int sum(int a,int b,int c)
{
	std::cout<<"a: "<<a <<" b: "<<b <<" c: "<<c;
	return a+b+c;
}

int main()
{
	//传入函数,与要绑定的参数值
	auto f = std::bind(sum,1,2,3);
	int result = f();              //绑定的函数对象调用
	std::cout<< " sum: " <<result; //结果: a: 1 b: 2 c: 3 sum: 6
	return 0;
}
使用占位符

可以使用 std::placeholders 中的占位符(_1,_2,_3 ...)来代替被绑定的实际参数

复制代码
#include<iostream>
#include<functional>
using namespace std::placeholders;

int sum(int a,int b,int c)
{
	std::cout<<"a: "<<a <<" b: "<<b <<" c: "<<c;
	return a+b+c;
}

int main()
{
	auto f = std::bind(sum,1,_1,3);
	int result = f(5);
	std::cout<< " sum: " <<result;  //结果: a: 1 b: 5 c: 3 sum: 9
	return 0;
}
使用变量作为绑定参数

注意变量是作为值传入的,因此后续修改变量,不会影响到函数

复制代码
#include<iostream>
#include<functional>
using namespace std::placeholders;

int sum(int a,int b,int c)
{
	std::cout<<"a: "<<a <<" b: "<<b <<" c: "<<c;
	return a+b+c;
}

int main()
{
	int n = 6;
	auto f = std::bind(sum,1,2,n);
	n = 99;
	int result = f(5);
	std::cout<< " sum: " <<result;  //结果: a: 1 b: 2 c: 6 sum: 9
	return 0;
}

如果想要变量以引用方式传入,需要使用std::cref();

复制代码
	int n = 6;
	auto f = std::bind(sum,1,2,std::cref(n));
	n = 99;
	int result = f(5);
	std::cout<< " sum: " <<result;  //结果: a: 1 b: 2 c: 99 sum: 102
	return 0;

注:cref()与ref()其中 c 指的是const

相关推荐
码客-ygluu4 小时前
一个通用游戏数据服务器
c++·架构
another heaven4 小时前
【C/C++ Ranges 是零开销抽象吗?拆开管道、惰性求值和编译期膨胀】
c语言·开发语言·c++
YLCHUP7 小时前
【思维&图论建模】题解:债权(debt)_图论_建模_思路转化_思维题目_C++算法竞赛
c++·笔记·算法·数学建模·贪心算法·深度优先·图论
xiaoye-duck7 小时前
《C++ 项目:手写大模型接入 SDK》会话模块整合:内存 SessionManager 与 DataManager 持久化联动
开发语言·数据库·c++·语言模型
思麟呀7 小时前
背包DP(01背包+完全背包)
c++·算法
旖旎夜光9 小时前
【C++ 基础入门】C++11 新特性(中):右值引用、移动语义与完美转发
开发语言·c++·笔记·学习
ShineWinsu9 小时前
对于Qt:QTabWidget常见属性的解析
开发语言·数据库·c++·qt·浏览器·qtabwidget·标签页
俊俊几年的10 小时前
动态规划(Dynamic Programming)详解:从入门到 LeetCode Hot 100
linux·c++·算法·leetcode·嵌入式·动态规划·c
老歌老听老掉牙1 天前
案例 7:二维 Rosenbrock 函数最小值(香蕉函数)
c++·pso
Severus_black1 天前
【C++初阶】Stack、Queue算法题大练兵!
c语言·c++·算法·stl