包装器c++11

1. 包装器

1.1 function

std::function 是⼀个类模板,也是⼀个包装器。 std::function 的实例对象可以包装存
储其他的可以调⽤对象,包括函数指针、仿函数、 lambda 、 bind 表达式等,存储的可调⽤对
象被称为 std::function 的⽬标。若 std::function 不含⽬标,则称它为。调⽤**
std::function 的⽬标*导致抛出 std::bad_function_call 异常。*

格式形式

Ret是返回类型,Args是可变参数。


function的适用环境:

当我们想要在一个容器里面存储,可调用函数的类型有很多,函数指针,仿函数,和lambda表达式。它们的类型都不一样。lambda的表达式类型我们也不知道啊,只有编译器才能推导。

function就可以很好处理这种情况,它利用类型擦除,隐含类型,把它们储存在一块空间,减少空间的使用.

1.1.1对于全局函数,仿函数,lambda

cpp 复制代码
using namespace std;
//function的包装器的用法
int fun(int x,int y ) {
	return x + y;
}

struct funter {

	int operator()(int x,int y) {

		return x + y;
	}

};

class op {
public:
	static int cun(int x,int y) {
		return x + y;
	}
	//非静态成员函数
	int con(int x, int y) {
		return x + y;
	}


};


int main() {
	//函数指针的类型复杂,仿函数的类型,lambda表达式类型我们不知道,一般都是编译器推导的。
	//可调用对象的类型都不一样,那我们怎么才能储存在一个容器里面了。
	//这个需要利用到function,它会隐含可调用函数的类型,然后存在在一块空间。function里面用到一个叫类型擦除的方法。
	//function的格式,function<返回类型<参数>>;
	vector<std::function<int(int , int )>> v;
	std::function<int(int , int )> f1 = fun;//参数的括号不要写错了
	std::function<int(int , int )> f2 = funter();//参数列表只需要类型,不要参数名。
	std::function<int(int , int )> f3 = [](int x, int y) {return x + y; };
cpp 复制代码
vector<std::function<int(int , int )>> v;
	std::function<int(int , int )> f1 = fun;//参数的括号不要写错了
	std::function<int(int , int )> f2 = funter();//参数列表只需要类型,不要参数名。
	std::function<int(int , int )> f3 = [](int x, int y) {return x + y; };
	cout << f1(1, 1) << endl;
	cout << f2(1, 1) << endl;
	cout << f3(1, 1) << endl;
	v.push_back(f1);
	v.push_back(f2);
	v.push_back(f3);
	for (auto& e : v) {
		cout << e(2,3) << endl;
	}

代码运行如下:


1.1.2成员函数的包装

对于成员函数指针的包装,有许多值得注意的地方。

cpp 复制代码
class op {
public:
	static int cun(int x,int y) {
		return x + y;
	}
	//非静态成员函数
	int con(int x, int y) {
		return x + y;
	}


};
cpp 复制代码
//包装成员函数
	//静态成员函数
	op t3;
	function<int(int, int)> d1 = &op::cun;//对于成员函数,获取函数指针必须前面加类域//静态前面可以加&
	function<int(op*,int, int)> d2 = &op::con;//这里参数con函数里面成员函数,还有隐含的this指针。
	function<int(op, int, int)> d3 = &op::con;//还可以传这个,
	function<int(op&&,int, int)> d4 = &op::con;

	cout << d1(1, 1)<<endl;
	cout << d2(&t3,2, 1) << endl;
	cout << d3(op(),4, 1) << endl;
	cout << d4(op(),6, 1) << endl;
	cout << d4(move(t3), 7, 3) << endl;

首先对于static静态成员函数需要加域名,&符号可以加,但是为了统一推荐加

对于成员函数,访问函数的指针,必须加&, function<int(op*,int, int)> d2 = &op::con;再看这个参数,里面为什么有op*,因为成员函数里面有this指针。参数可以是对象,对象指针,右值引用,左值引用。

为什么可以传op,op*?

因为this指针不是直接传给函数,不能显示传,底层通过对象(.*)调用,或者对象指针->*调用

cpp 复制代码
///op* t1=&t3;//这个指针要初始化,因为//op*t1只是声明
	op* t1 = new op();
	auto ptr = &op::con;
	cout<<(t1->*ptr)(1, 2)<<endl;
	op t2;
	cout << (t2.*ptr)(3, 4) << endl;

输出的时候:对于成员函数,我们参数要传对象,匿名对象。对象的地址。

运行代码:

1.2 算法题function的用法

1.3bind

  • 对于bind我们可以把看它看作一个函数模板,一个可调用对象的包装器,一个函数适配器。它把一个可调用函数处理后,返回一个可调用函数参数。bind可改变参数个数和顺序。它的头文件是<functional>。

  • 调⽤bind的⼀般形式: auto newCallable = bind(callable,arg_list); 其中 newCallable本⾝是⼀个可调⽤对象,arg_list是⼀个逗号分隔的参数列表,对应给定的callable的 参数。当我调⽤newCallable时,newCallable会调⽤callable,并传给它arg_list中的参数。

  • arg_list中的参数可能包含形如_n的名字,其中n是⼀个整数,这些参数是占位符,表newCallable的参数,它们占据了传递给newCallable的参数的位置。数值n表⽰⽣成的可调⽤对象 中参数的位置:_1为newCallable的第⼀个参数,_2为第⼆个参数,以此类推。_1/_2/_3....这些占 位符放到placeholders的⼀个命名空间中。

cpp 复制代码
int fun(int x,int y) {
	return (x - y) * 10;

}

int fun1(int x, int y,int z) {
	return (x - y-z) * 10;

}


int main() {

	auto d1 = bind(fun, _1, _2);
	cout << d1(10, 5)<<endl;
	auto d2 = bind(fun, _2, _1);//bind 本质是返回一个仿函数对象。
	cout << d2(10, 5) << endl;//这里调用可调用函数,调用它的operator(),然后再调用fun函数。

	//调整参数个数
	auto d3 = bind(fun1, 15, _1, _2);
	cout << d3(10, 5) << endl;
	auto d4 = bind(fun1, _1, 15, _2);
	cout << d4(10, 5)<<endl;

使用场景:

绑定this指针的参数

cpp 复制代码
function<int(op, int, int)> d3 = &op::con;//还可以传这个,
//	function<int(op&&,int, int)> d4 = &op::con;
//
//	cout << d1(1, 1)<<endl;
//	cout << d2(&t3,2, 1) << endl;
//	cout << d3(op(),4, 1) << endl;
//	cout << d4(op(),6, 1) << endl;


相比较
//对于类成员函数的包装,我们调用的时候,每次都需要传类对象,来调用隐含的this指针。我们可不可以把强制把参数设置。
	function<int( int, int)> d5 = bind(&op::con,op(),_1,_2);//只有两个可变参数
	cout << d5(16, 4)<<endl;

计算利息的场景

cpp 复制代码
int sum(double x, double money, int year) {
	double ret = money;
	while (year) {
		ret = ret + ret * x;

		year--;
	}
	return ret-money;
}


//对于银行利息的计算
	//一般利率是固定的,
	auto _m_1 = bind(sum, 0.1, _1, 1);
	auto _m_3 = bind(sum, 0.1, _1, 3);
	auto _m_5 = bind(sum, 0.1, _1, 5);
	cout << _m_1(10000) << endl;
	cout << _m_3(10000) << endl;
	cout << _m_5(10000)<<endl;
相关推荐
阿里嘎多学长1 小时前
2025-12-05 GitHub 热点项目精选
开发语言·程序员·github·代码托管
王光环1 小时前
C语言写exe脚本
c语言·开发语言
8278209371 小时前
python scp 备份
开发语言·python
獭.獭.1 小时前
C++ -- 二叉搜索树
数据结构·c++·算法·二叉搜索树
leoufung1 小时前
图解除法查询问题:用 C 语言和 DFS 实现带权有向图的路径乘积
c语言·开发语言·深度优先
poggioxay1 小时前
JAVA零基础入门知识3(持续更新中)
java·开发语言·python
鹤归时起雾.1 小时前
Vue3响应式编程核心指南
开发语言·vue3
charlie1145141912 小时前
深入理解CC++的编译与链接技术8:Windows和Linux是如何搜寻动态库的?
c语言·c++·动态库·编译·编译技术
郝学胜-神的一滴2 小时前
Linux信号四要素详解:从理论到实践
linux·服务器·开发语言·网络·c++·程序人生