std::function与std::bind

1.可调用对象

1.1 函数指针

void myfunc(int tv)
{
	cout<<"myfunc()函数执行了,tv"<<tv<<std::endl;
}
//主函数main
void(*pmf)(int) = myfunc;//定义函数指针并给初值,myfunc也可以写成&myfunc,是一样的效果
pmf(15);			     //调用函数,这就是一个可调用对象

1.2 具有operator()成员函数的类对象(仿函数/函数对象)

class TC
{
public:
    void operator()(int tv)
    {
        std::cout<<"TC::operator()执行了,tv = "<<tv<<std::endl;
    }
};
//主函数
TC tc;
tc(20);	//调用的是()函数,这是一个可调用对象,等价于tc.operator()(20);

1.3 可被转换为函数指针的类对象

class TC2
{
public:
    using tfpoint = void(*)(int);//定义tfpoint是void类型函数且参数为int类型的函数指针
    static void mysfunc(int tv)
    {
        cout<<"TC2::mysfunc()静态成员函数执行了,tv = "<<tv<<std::endl;
    }
    operator tfpoint(){return mysfunc;}//类型转换运算符/类型转换函数
};
//主函数
TC2 tc2;
tc2(50);//先调用tfpoint,再调用mysfunc;这就是一个可调用对象,等价于tc2.operator TC2::tfpoint()(50);

1.4 类成员函数指针

//class TC里面
void ptfunc(int tv)
{
    std::cout<<"TC::ptfunc()执行了,tv = "<<tv<<std::endl;
}
int m_a;
//主函数
TC tc3;
void(TC:: *myfpointpt)(int) = &TC::ptfunc;//类成员函数指针变量myfpointpt定义并被给初值
(tc.*myfpointpt)(68);				      //要调用函数,就必须用到对象tc3

1.5 总结

  • std::function可以把这些可调用对象的调用形式统一一下

2.std::function可调用对象包装器

2.1 绑定普通函数

std::function<void(int)> f1 = myfunc;//绑定一个普通函数myfunc,注意<>中的格式
f1(100);							 //调用普通函数

2.2 绑定类的静态成员函数

  • TC类中增加一个Public修饰的静态成员函数
public:
	static int stcfunc(int tv)
	{
		cout<<"TC::stcfunc()静态函数执行了,tv = "<<tv<<std::endl;
		return tv;
	}
//main函数
std::function<int(int)> f3 = TC::stcfunc();//绑定一个类的静态成员函数
fs2(110);								   //调用静态成员函数

2.3 绑定仿函数

  • 例一
class TC
{
public:
    TC()
    {
        m_a = 1;
    }
    void operator()(int tv)
    {
        std::cout<<"TC::operator()执行了,tv = "<<tv<<std::endl;
    }
    void ptfunc(int tv)
    {
        std::cout<<"TC::ptfunc()执行了,tv = "<<tv<<std::endl;
    }
    int m_a;
};
//主函数
TC tc3;
std::function<void(int)>f3 = tc3;
  • 例二
class TC2
{
public:
    using tfpoint = void(*)(int);//定义tfpoint是void类型函数且参数为int类型的函数指针
    static void mysfunc(int tv)
    {
        cout<<"TC2::mysfunc()静态成员函数执行了,tv = "<<tv<<std::endl;
    }
    operator tfpoint(){return mysfunc;}//类型转换运算符/类型转换函数
};
//主函数
TC tc3;
std::function<void(int)>f3 = tc3;
f3(120);//执行了void operator()(int tv)
TC2 tc4;
std::function<void(int)>f4 = tc4;//
f4(120);						 //TC2::mysfunc()静态成员函数执行了,tv = 150

2.4 范例演示

  • 范例一
class CB
{
    std::function<void()>fcallback;
public:
    CB(const std::function<void()>&f)
    : fcallback(f)
    {
        int i;
        i = 1;
    }

    void runcallback(void)
    {
        fcallback();
    }
};

class CT
{
public:
    CT()                //构造函数
    {
        std::cout<<"CT::CT()执行"<<std::endl;
    }

    CT(const CT&)       //拷贝构造函数
    {
        std::cout<<"CT::CT(const CT&)执行"<<std::endl;
    }

    void operator()(void)
    {
        std::cout<<"CT::operator()执行"<<std::endl;
    }
};



int main()
{
    CT ct;                  //可调用对象,这行导致CT构造函数的执行
    CB cb(ct);              //cb需要可调用对象作为参数来构造,因为有operator()所以ct可以转为const std::function<void(void)>&对象
                            //这行导致CT拷贝构造函数被执行多次
    cb.runcallback();       //CT::operator()执行
    return 0;
}
  • 范例二
void mycallback(int cs,const std::function<void(int)>&f)
{
    f(cs);
}

void runfunc(int x)
{
    cout<<x;
}

int main()
{
    for(int i = 0;i<10;++i)
    {
        mycallback(i,runfunc);
    }
    cout<<endl;
    return 0;
}

在这里插入图片描述

3.std::bind绑定器

3.1 使用模板一般如下

std:;bind(待绑定的函数对象/函数指针/成员函数指针,参数绑定值1,参数绑定值2,。。。参数绑定值n);

3.2 std::bind定义分类

  • 1)将可调用对象和参数绑定到一起,构成一个仿函数,所以可以直接调用
  • 2)如果函数有多个参数,可以绑定部分参数,其他的参数再调用时指定

3.3 std::bind调用案例

一:
void myfunc1(int x,int y,int z)
{
	cout<<"x = " <<x<<",y = "<<y<<",z = "<<z<<endl;
}
//主函数
auto buf1 = std::bind(myfunc1,10,20,30);
bf1();//执行myfunc1函数,结果:x = 10;y = 20;z=30
二:
auto bf2 = std::bind(myfunc1,placeholders::_1,placeholders::_2,30);
bf2(5,15);		//x=5,y=15,z=30
//直接调用也可以
std::bind(myfunc1,placeholders::_1,placeholders_2,30)(10,20);//x=10,y=20,z=30
三:
void myfunc2(int&x,int& y)
{
	x++;
	y++;
}
int a = 2;
int b = 3;
auto bf4= std::bind(myfunc2,a,placeholders::_1);
bf(b);
四:绑定类成员函数
class CQ
{
public:
	void myfunpt(int x,int y)
	{
		cout<<"x="<<x<<",y="<<y<<endl;
		m_a = x;
	}
	int m_a = 0;//成员变量
};
//main主函数
CQ cq;
auto bf5 = std::bind(&CQ::myfunpt,&cq,placeholders::_1,placeholders::_2);//cq加&表示的就是不会生成临时对象
bf5(10,20);			//对成员函数的调用
五:绑定成员变量
class CQ
{
public:
	void myfunpt(int x,int y)
	{
		cout<<"x="<<x<<",y="<<y<<endl;
		m_a = x;
	}
    
    CQ()
    {
        printf("CQ::CQ()构造函数执行,this = %p\n",this);
    }

    CQ(const CQ&)
    {
        printf("CQ::CQ(const CQ&)拷贝构造函数执行,this = %p\n",this);
    }

    ~CQ()
    {
        printf("CQ::~CQ()析构函数执行,this = %p\n",this);
    }

	int m_a = 0;//成员变量
};
//main
CQ cq;
std::function<int&(void)>bf7 = std::bind(&CQ::m_a,&cq);
bf7() = 60;

在这里插入图片描述

4.总结

  • 1.std::bind的思想实际上是一种延迟计算的思想,将可调用对象保存起来,然后在需要的时候再调用
  • 2.std::function一般要绑定一个可调用对象,类成员函数不能被绑定。而std::bind更加强大,什么都能绑定。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值