C++新特性探究(十五):bind

相关博文:C++新特性探究(十四):function
相关博文:C++头文件<functional>和bind、placeholders占位符使用简单例子
相关博文:《Essential C++》笔记之设计一个泛型算法(二)
相关博文:C++Function Object Adapter之not1
相关博文:C++之再探参数绑定bind、bind1st、bind2nd、placeholders占位符
相关博文:C++新特性探究(十五):bind

bind语义

  bind 用来将可调用对象和参数一起进行绑定。可调用对象包括普通函数、全局函数、静态函数、类静态函数甚至是类成员函数,参数包括普通参数和类成员。绑定后的结果,可以使用 std::function 进行保存,并延迟调用到我们需要的时候。
在这里插入图片描述

一. 绑定普通函数与参数及占位

  bind绑定的顺序,也就是函数中形参的声明顺序。
  placeholders::_x中的序列是实参的顺序。

例1:
在这里插入图片描述
运行结果:
在这里插入图片描述
附例1代码:

//小问学编程
#include<iostream>
#include<functional>
using namespace std;
using namespace std::placeholders;

double myDivide(double x,double y)
{
    
    
	return x/y;
}

int main()
{
    
    
	//零个参数 return 10/2
	auto fn_five=bind(myDivide,10,2);
	cout<<fn_five()<<endl;

	//一个参数 return x/2             auto不可省
	auto fn_half=bind(myDivide,placeholders::_1,2);
	cout<<fn_half(10)<<endl;

	//一个参数 return 2/x
	auto fn_half2=bind(myDivide,2,placeholders::_1);
	cout<<fn_half(10)<<endl;

	//两个参数 return int x/y
	auto fn_rounding=bind<int>(myDivide,_1,_2);
	cout<<fn_rounding(10,3)<<endl;

	//反转参数 return y/x
	auto fn_invert=bind(myDivide,_2,_1);
	cout<<fn_invert(10,2)<<endl;

	return 0;
}

二. 绑定对象与成员及占位

  绑定对象及成员函数时,顺序是调用成员,对象,[参数]。成员,对象及参数不能有缺位,缺位可用 placeholders::_x 来占位。否则编译不过。

例2:
在这里插入图片描述
运行结果:
在这里插入图片描述

三. 函数重载情形

例3:

//小问学编程
#include<iostream>
#include<functional>
using namespace std;
using namespace std::placeholders;

int add(int x,int y)
{
    
    
	cout<<"int add(int x,int y)"<<endl;
	return x+y;
}
double add(double x,double y)
{
    
    
	cout<<"double add(double x,double y)"<<endl;
	return x+y;
}

class MyPair
{
    
    
public:
	int add(int x,int y)
	{
    
    
		cout<<"MyPair::int add(int x,int y)"<<endl;
		return x+y;
	}
	double add(double x,double y)
	{
    
    
		cout<<"double add(double x,double y)"<<endl;
		return x+y;
	}
};

int main()
{
    
    
	auto bindGlobalFunc=bind((int(*)(int,int))add,_1,_2);
	cout<<bindGlobalFunc(1,2)<<endl;

	auto bindGlobalFunc2=bind(static_cast<double(*)(double,double)>(add),_1,_2);
	cout<<bindGlobalFunc2(1,2)<<endl;

	MyPair mp;
	auto bindMemberFunc=bind(static_cast<double(MyPair::*)(double,double)>(&MyPair::add),mp,1,2);
	cout<<bindMemberFunc()<<endl;

	return 0;
}

运行结果:
在这里插入图片描述

四. bind小结

  (1)bind 预先绑定的参数需要传具体的变量或值进去,对于预先绑定的参数,是pass-by-value的。
  (2)对于不事先绑定的参数,需要传 std::placeholders 进去,从_1 开始,依次递增。placeholder 是 pass-by-reference 的。
  (3)bind 的返回值是可调用实体,可以直接赋给 std::function 对象。
  (4)对于绑定的指针、引用类型的参数,使用者需要保证在可调用实体调用之前, 这些参数是可用的。
  (5)类的 this 可以通过对象或者指针来绑定。

五. 多态之bind+function

  function 本是不可以包装类成员函数,但是 bind 的可以实现类成员函数的绑定, 然后赋给 fucntion 对象,亦即实现了间接性的包装。
  bind+function 可以实现接口统一的极大整合,这是多态吗?

例4:
在这里插入图片描述

附例4代码:

//小问学编程
#include <iostream>
#include <functional>
using namespace std;

void foo()
{
    
    
    cout<<"void foo()"<<endl;
}
void func(int a)
{
    
    
    cout<<"void func(int a)"<<endl;
}
class Foo
{
    
    
public:
    void method()
    {
    
    
        cout<<"Foo::void method()"<<endl;
    }
    void method2(string s)
    {
    
    
        cout<<"Foo:void method2()"<<endl;
    }
};
class Bar
{
    
    
public:
    void method3(int a,string s)
    {
    
    
        cout<<"Bar:void method3()"<<endl;
    }
};
function<void(void)> f;

int main()
{
    
    
    f = bind(foo);
    f();
    f= bind(func,1);
    f();
    Foo foo;
    f = bind(&Foo::method,&foo);
    f();
    f = bind(&Foo::method2,&foo,"china");
    f();

    Bar bar;
    f = bind(&Bar::method3,&bar,10,"china");
    f();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43297891/article/details/113766985
今日推荐