• 正文
    • 1 std::bind
    • 2 实例
    • 3 总结
  • 相关推荐
申请入驻 产业图谱

C++实用函数:bind函数绑定

04/14 11:35
574
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

本篇来介绍了C++中bind功能。

1 std::bind

在 C++ 里,std::bind 是一个函数模板,其作用是创建一个可调用对象,该对象可绑定到一组参数上。std::bind 的函数原型如下:

template< class F, class... Args >
/*unspecified*/ bind( F&& f, Args&&... args );

template< class R, class F, class... Args >
/*unspecified*/ bind( F&& f, Args&&... args );

参数

F:这是要绑定的可调用对象(像函数、函数指针、成员函数指针、函数对象等)的类型。

Args:这是要绑定的参数的类型包。

f:需要绑定的可调用对象。

args:要绑定到可调用对象上的参数。

R:可调用对象的返回类型(可选)。

返回值

std::bind

 返回一个未指定类型的可调用对象,这个对象存储了 f 和 args 的副本或者引用,并且可以在后续被调用。

2 实例

2.1 基础的bind功能

被绑定的函数支持参数和返回值,参数通过std::placeholders::_1的形式,注意这里_1是特定的形式,表示第一个参数

//g++ test1.cpp -std=c++11 -o test1
#include <functional>
#include <string>


std::string myFunc(int a, float b)
{
    char buf[256];
    sprintf(buf, "receive a:%d, b:%.2f", a, b);
    returnstd::string(buf);
}

int main()
{
    auto bindFunc = std::bind(myFunc, std::placeholders::_1, std::placeholders::_2);
    std::string res = bindFunc(5, 8.63);
    printf("res:%sn", res.c_str());
    
    return0;
}

示例代码运行结果如下:

2.2 bind时调换参数的顺序

如果调换参数顺序的需求,可以通过指定placeholders的顺序,来实现。

比如,myFunc的第二个参数是float类型,如果在执行调用函数时,第一个参数传入float,则在绑定函数的第一个位置,写为 std::placeholders::_2即可。

//g++ test2.cpp -std=c++11 -o test2
#include <functional>
#include <string>


std::string myFunc(int a, float b)
{
    char buf[256];
    sprintf(buf, "receive a:%d, b:%.2f", a, b);
    returnstd::string(buf);
}

int main()
{
    auto bindFunc = std::bind(myFunc, std::placeholders::_2, std::placeholders::_1);
    std::string res = bindFunc(3.14, 6);
    printf("res:%sn", res.c_str());
    
    return0;
}

示例代码运行结果如下:

2.3 结合C++类使用bind

上面介绍的函数都不涉及到类,而C++中一般都会使用类,在类中以及类中的函数,如果使用bind,主要区别就是要再额外传入对应的类的指针。

这里演示了3种情况:

    MyClass1进行一个实例化,然后在main中bind其成员函数MyClass2是一个单例模式,在main中bind的时候进行实例化MyClass3,演示在类内部进行bind,类的指针就是this指针
//g++ test3.cpp -std=c++11 -o test3
#include <functional>
#include <string>


class MyClass1
{
public:
    std::string myFunc(int a, float b)
    {
        char buf[256];
        sprintf(buf, "receive a:%d, b:%.2f", a, b);
        returnstd::string(buf);
    }    
};

class MyClass2
{
public:
    static MyClass2 &getInstance()
    {
        static MyClass2 instance;
        return instance;
    }
    
    std::string myFunc(int a, float b)
    {
        char buf[256];
        sprintf(buf, "receive a:%d, b:%.2f", a, b);
        returnstd::string(buf);
    }    
};

class MyClass3
{
public:
    std::string myFunc(int a, float b)
    {
        char buf[256];
        sprintf(buf, "receive a:%d, b:%.2f", a, b);
        returnstd::string(buf);
    } 
    
    void testBind()
    {
        auto bindFunc = std::bind(&MyClass3::myFunc, this, std::placeholders::_1, std::placeholders::_2);
        std::string res = bindFunc(33, 3.45);
        printf("res:%sn", res.c_str()); 
    }  
};

int main()
{
    MyClass1 myClass1;
    auto bindFunc1 = std::bind(&MyClass1::myFunc, &myClass1, std::placeholders::_1, std::placeholders::_2);
    std::string res1 = bindFunc1(11, 1.23);
    printf("res:%sn", res1.c_str());

    auto bindFunc2 = std::bind(&MyClass2::myFunc, MyClass2::getInstance(), std::placeholders::_1, std::placeholders::_2);
    std::string res2 = bindFunc1(22, 2.34);
    printf("res:%sn", res2.c_str());
    
    MyClass3 myClass3;
    myClass3.testBind();
      
    return0;
}

示例代码运行结果如下:

2.4 std::ref的使用

在进行bind的时候,也可以不使用placeholders占符,直接传入具体的参数。

这里要注意,直接传入值,即使函数参数定义的是引用,但实际效果也是按值传递。如果需要按引用传递,需要使用std::ref,如下例中的第一个演示。当然,如果是使用placeholders占符,就不需要考虑std::ref了,就会正常的按定义的引用类型运行。

//g++ test4.cpp -std=c++11 -o test4
#include <functional>
#include <string>


std::string myFunc(int &a, float &b)
{
    char buf[256];
    sprintf(buf, "receive a:%d, b:%.2f", a, b);
    a += 1;
    b += 1;
    returnstd::string(buf);
}

int main()
{
    int a = 100;
    float b = 66.88;
    printf("a:%d, b:%.2fn", a, b);
    auto bindFunc1 = std::bind(myFunc, a, std::ref(b));
    std::string res1 = bindFunc1();
    printf("res1:%sn", res1.c_str());
    printf("a:%d, b:%.2fn", a, b);
    
    auto bindFunc2 = std::bind(myFunc, std::placeholders::_1, std::placeholders::_2);
    std::string res2 = bindFunc2(a, b);
    printf("res2:%sn", res2.c_str());
    printf("a:%d, b:%.2fn", a, b);
    
    return0;
}

示例代码运行结果如下:

2.5 将bind作为函数参数实现函数传递

最后来看一个特殊的,函数的参数是一个函数类型,如下面的MyClass类中的myFunc,它需要传入一个函数,这个函数有两个float类型的参数,并且返回一个float,在myFunc中定义了两个参数的具体的值。

这个有什么用呢,比如在MyCalc类中定义sum求和函数和sub求差函数,这样MyClass类就可以使用外部的MyCalc类中定义的函数功能,来实现一些数学运算。

//g++ test5.cpp -std=c++11 -o test5
#include <functional>
#include <string>

class MyCalc
{
public:
    float sum(float a, float b)
    {
        return a + b;
    }

    float sub(float a, float b)
    {
        return a - b;
    }
};

class MyClass
{
public:
    void myFunc(std::function<float(float,float)> calcFunc)
    {
        float a = 55;
        float b = 22;
        float res = calcFunc(a, b);
        printf("a:%.2f, b:%.2f, res:%.2fn", a, b, res);
    }
};

int main()
{
    MyCalc myCalc;
    MyClass myClass;
    
    auto bindFunc1 = std::bind(&MyCalc::sum, &myCalc, std::placeholders::_1, std::placeholders::_2);
    myClass.myFunc(bindFunc1);
    
    auto bindFunc2 = std::bind(&MyCalc::sub, &myCalc, std::placeholders::_1, std::placeholders::_2);
    myClass.myFunc(bindFunc2);
    
    return0;
}

示例代码运行结果如下:

3 总结

本篇介绍了C++中bind功能的使用,并通过实际的例里来演示其使用场景。

点赞
收藏
评论
分享
加入交流群
举报

相关推荐

登录即可解锁
  • 海量技术文章
  • 设计资源下载
  • 产业链客户资源
  • 写文章/发需求
立即登录