C++11 - 5 - function包装器

本文详细介绍了C++11中的function包装器,包括其作用、用法以及如何包装类内函数。同时,探讨了function包装器如何提高模板效率,以及bind绑定的功能,如调整传参顺序和参数个数。通过示例代码展示了function和bind的实际应用,帮助理解其工作原理。
摘要由CSDN通过智能技术生成

c++

前言:

Vue框架:从项目学Vue
OJ算法系列:神机百炼 - 算法详解
Linux操作系统:风后奇门 - linux

function包装器:

调用对象:

  • 调用对象分类:
int ret = func(x);
//func可能是什么呢?
  1. 函数名
  2. 函数指针
  3. 仿函数对象
  4. lambda表达式对象

模板效率:

  • 太多的调用对象,导致模板使用效率低下:
template<class F, class T>
T useF(F f, T t){
	static int count = 0;	//一定为static
	cout<<"count : "<<count++<<endl;
	cout<<"&count : "<<&count<<endl;
	return f(x);
}

//f的三种类型:
double func1(double x){
	return i/2;
}
struct Functor{
	double operator()(double x){
		return x/3;
	}
};
auto func2 = [](double x){
	return x/4;
};

int main(){
	useF(func1, 10);
	useF(Functor(), 10);
	useF(func2, 10);
	return 0;
}
  • 运行结果:三个不同的count地址
  • 原因分析:
    1. class F对应三种不同的具体类型
    2. 实例化出三种useF()函数
    3. 每种useF()函数含有自己创建的static变量

包装器:

作用:

  • 将不同的可调用对象包装为同一类型
    模板识别时也是视为同一类别
  • 相当于调用对象的类型增加,
    尤其是原本不好使用的auto,
    现在也可以根据参数和返回值将类型记为function<()>;

用法:

  • 头文件:
#include <functional>
  • 声明:
//对函数/函数指针:
function<double(double)> f1 = func1;

//对仿函数类:
function<double(double)> f2 = Functor();

//对lambda表达式:
function<double(double)> f3 = func2;

包装类内函数:

包装类内静态函数:

  • 几乎和包装非类内函数一样
class Calculator{
	public:
		int sum(int x, int y){
			return x+y;
		}
};
int main(){
	function<int(int, int)> f4 = &Calculator::sum;	//可不加&
	return 0;
}

包装类内非静态函数:

  • 和包装普通函数有两点区别:
    1. 加 & 符号
    2. 包装类内声明静态函数所属类
    3. 调用时需要传入一个实例对象
class Calculator{
	public:
		static int sub(int x, int y){
			return x+y;
		}
};
int main(){
	function<int(Calculator, int, int)> f4 = &Calculator::sub;
	f4(Calculator(), 1, 2);
	return 0;
}

证明:

  • 证明经过包装器后,所有函数都属于同一类:
#include <iostream>
#include <cstring>
#include <functional>
using namespace std;
template<class F, class T>
T useF(F f, T t){
	static int count = 0;	//一定为static
	cout<<"count : "<<count++<<endl;
	cout<<"&count : "<<&count<<endl;
	return f(t);
}

double func1(double x){
	return x/2;
}
struct Functor{
	double operator()(double x){
		return x/3;
	}
};
auto func2 = [](double x){
	return x/4;
};
class Test{
	public:
		static double sfunc(double x){
			return x/5;
		}
		double dfunc(double x){
			return x/6;
		}
};
int main(){
	function<double(double)> f1 = func1;
	function<double(double)> f2 = Functor();
	function<double(double)> f3 = func2;
	useF(f1, 10);
	useF(f2, 10);
	useF(f3, 10);
	function<double(double)> f4 = Test::sfunc;
	function<double(Test, double)> f5 = &Test::dfunc;
	useF(f4, 10);
	cout<<"f5:"<<f5(Test(), 10);
	/*
		useF(f5, 10);
		f5和f1~f4传参不同,所以  暂时  不能放入useF()函数中
		学完绑定后即可
	*/
	return 0;
}
  • 运行结果:
    function<>

bind绑定:

作用:

调整传参顺序:

  • placeholders::_n:表示当前位置值传递给函数第n个参数
void func(int x, int y){
	cout<<"x:"<<x <<"  "<<"y:"<<y<<endl;
}
function<int(int ,int)> f1 = bind(func, placeholders::_1, placeholders::_2);
f1(1, 2);

function<int(int ,int)> f2 = bind(func, placeholders::_2, placeholders::_1);
f2(1, 2);
  • 运行结果:
    1 2
    2 1

调整参数个数:

  • 为类内非静态函数,绑定类 + 提供对象:
class Test{
	public:
		static double sfunc(double x){
			return x/5;
		}
		double dfunc(double x){
			return x/6;
		}
};

function<double(Test, double)> f5 = &Test::dfunc;
f5(Test(), 10);
function<double(Test, double)> f6 = bind(&Test::dfunc, Test());
f6(10);
  • 将类内非静态函数 + 类对象,一步为function()绑定
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

starnight531

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值