C++11中的std::function和std::bind

1.std:bind

std:bind是一个函数模板,可以用来绑定一切函数

1.1 绑定普通成员函数,普通静态成员函数,普通模板函数

例子:

#include <functional>
#include <iostream>
#include <cstdio>

void fun(int a, int b)
{
    std::cout <<a+b<<std::endl;
}

int main()
{
    auto funBind = std::bind(fun, 4, 6);
    funBind();
    return 0;
}

结果为

10

上面的例子中函数fun被绑定到了funBind中,fun中的参数被绑定到了一个固定的值,当然你也可以不指定它的值,在绑定值时给它一个缺省值,即绑定到占位符(std::placeholders)上,如下:

#include <functional>
#include <iostream>
#include <cstdio>

void fun(int a, int b)
{
    std::cout << a + b << std::endl;
}

//绑定到静态函数
static void staticfun(int a, int b)
{
    std::cout << a + b << std::endl;
}

//绑定到模板函数
template<typename A, typename B>
inline void addFun(A a, B b)
{
    std::cout << a + b << std::endl;
}

int main()
{
    auto funBind = std::bind(fun, std::placeholders::_1, 6);
    funBind(4);


    auto funBind1 = std::bind(staticfun, std::placeholders::_1, std::placeholders::_2);
    funBind1(5, 6);

    auto funBind2 = std::bind(addFun<int,int>, std::placeholders::_1, std::placeholders::_2);
    funBind2(6, 6);

    return 0;
}

结果:

10
11
12

需要注意的是:绑定到模板函数的时候,第一个参数需要指定参数的类型

1.2 绑定类成员函数,类静态成员函数,类模板函数

需要注意的是:在绑定类成员函数时,bind的第一个参数为对象的成员函数指针,第二个参数为一个具体的对象实例指针,如下

#include <functional>
#include <iostream>
#include <cstdio>

class S {
public:
    void fun(int a, int b)
    {
        std::cout << a + b << std::endl;
    }

    //绑定到静态函数
    static void staticfun(int a, int b)
    {
        std::cout << a + b << std::endl;
    }

    template<typename A, typename B>
    inline void addFun(A a, B b)
    {
        std::cout << a + b << std::endl;
    }
    
};
int main()
{
    S s;

    auto funBind = std::bind(&S::fun,&s,std::placeholders::_1, 6);
    funBind(4);

    auto funBind1 = std::bind(&S::staticfun, std::placeholders::_1, std::placeholders::_2);
    funBind1(5,6);
 
    auto funBind2 = std::bind(&S::addFun<int,int>, &s,std::placeholders::_1, std::placeholders::_2);
    funBind2(6, 6);

    return 0;
}

结果:

10
11
12

需要注意的是成员函数的访问权限为public,在绑定静态成员函数时,第二个参数不需要指定具体对象实例的地址

1.3 绑定引用参数

先看例子:

#include <functional>
#include <iostream>
#include <cstdio>

int add(int& a, const int& b)
{ 
    return a+b; 
}

int main()
{
    int a = 2, b = 4;

    auto funcBind = std::bind(add, std::ref(a), std::cref(b));

    std::cout << funcBind() << std::endl;

    return 0;
}
```c
结果为:
```c
6

在上面的例子a为普通引用,在绑定传递值时调用ref即可,而b为常量引用,在绑定传递值时调用cref即可

1.4 绑定lambda表达式

#include <functional>
#include <iostream>
#include <cstdio>

auto lambda = [](int a, int b)
{
    return a + b;
};

int main()
{
    int a = 2, b = 4;

    auto funcBind = std::bind(lambda, a, b);

    std::cout << funcBind() << std::endl;

    return 0;
}

结果:

6

2.std::function

2.1 封装普通函数/静态函数/lambda表达式

std::function是一个函数模板类,是一个类,定义在头文件可以用其定义不同的对象,对象的类型可以是普通函数,静态函数以及Lambda表达式,在不用std::function之前,定义一个函数指针通常用以下方法定义,如:

typedef void (*funPtr)(int,int);

使用std::function之后,这样定义

std::function<void(int ,int)> funPtr;

通常这样子使用,先定义一个函数,再将这个函数指针赋值给一个std::function对象,如下

#include <functional>
#include <iostream>
#include <cstdio>

void fun(int a, int b)
{
    std::cout << a + b << std::endl;
}

static void fun1(int a, int b)
{
    std::cout << a + b << std::endl;
}

auto lambda = [](int a, int b)
{
    std::cout << a + b << std::endl;
};

int main()
{
    std::function<void(int, int)> funPtr = fun;
    funPtr(1, 2);

    std::function<void(int, int)> funPtr1 = fun1;
    funPtr1(2, 2);

    std::function<void(int, int)> funPtr2 = lambda;
    funPtr2(3, 2);

    return 0;
}

结果:
3
4
5

2.2 绑定成员函数/静态成员函数/函数模板/成员变量

在封装成员函数/静态成员函数时,std::functionstd::bind搭配使用

#include <functional>
#include <iostream>
#include <cstdio>

class S {
public:
    int num;
    void fun(int a, int b)
    {
        std::cout << a + b << std::endl;
    }

    //绑定到静态函数
    static void staticfun(int a, int b)
    {
        std::cout << a + b << std::endl;
    }

    template<typename A, typename B>
    inline void addFun(A a, B b)
    {
        std::cout << a + b << std::endl;
    }

};
int main()
{
    S s;

    //错误的,不可以使用 std::function指向类的非静态成员
    //std::function<void(int, int)> funBind = std::bind(&S::fun, &s, std::placeholders::_1, 6);
    //funBind(4);

    std::function<void(int, int)> funBind1 = std::bind(&S::staticfun, std::placeholders::_1, std::placeholders::_2);
    funBind1(5, 6);

    std::function<void(int, int)> funBind2 = std::bind(&S::addFun<int, int>, &s, std::placeholders::_1, std::placeholders::_2);
    funBind2(6, 6);

    //绑定成员变量
    std::function<int& ()> MyValue = std::bind(&S::num, &s);
    MyValue() = 1000;//相当于s.num=1000
    std::cout << "num = "<<s.num<< std::endl;

    return 0;
}

结果:

11
12
num = 1000

需要注意的是不可以使用 std::function指向类的非静态成员,可以用函数指针的形式表示或者在类中直接绑定,如下:

#include <iostream>
#include <vector>
#include <functional>

class Father
{
public:
    void Called() {
        for (int i = 0; i < Vec.size(); i++)
            Vec[i]();
    }
protected:
    std::vector<std::function<void()>> Vec;
};
class Son : public Father
{
public:
    Son()
    {
        std::function<void()> fun1 = std::bind(&Son::A, this);
        std::function<void()> fun2 = std::bind(&Son::B, this);
        Vec.push_back(fun1);
        Vec.push_back(fun2);
    }
private:
    void A() { std::cout << "A\n"; }
    void B() { std::cout << "B\n"; }
};

int main()
{
    Son d;
    d.Called();
    return 0;
}

结果:

A
B
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值