C++11中引入的std::function类模板是一个函数包装器,它可以将任何可调用的类型(如函数、函数对象等)包装成一个可拷贝的对象。

例如,我们需要向一个类注册一个回调函数,当某个事件发生的时候,这个类调用我们提供的函数,以完成我们期望的操作。这时,就可以通过向该类传递一个std::function对象,来帮助我们完成这种操作。

std::function的常见用法

#include<iostream>
#include<functional>
 
int global_func(int a, int b) {
    return a + b;
}
int overload_func(int a, int b) {
    return a + b;
}
int overload_func(int a, double b) {
    return a + static_cast<int>(b);
}
template<typename T, typename U>
int template_func(T a, U b) {
    return a + b;
}
class C {
public:
    int class_func(int a, int b) {
        return a + b;
    }
};
auto lambda_func = [](int a, int b){ return a + b; };
int main()
{
    // 1. 普通函数
    std::function<int(int, int)> f1 = global_func;
    // 2. 重载函数
    std::function<int(int, int)> f2 = static_cast<int(*)(int,int)>(overload_func);
    // 3. 模板函数
    std::function<int(int, int)> f3 = template_func<int,int>;
    // 4. 成员函数
    std::function<int(C*, int, int)> f4 = &C::class_func;
    C c;
    f4(&c, 1, 2);
    // 5. lambda
    std::function<int(int, int)> f5 = lambda_func;
    // 6. std::bind返回值
    std::function<int(int)> f6 = std::bind(global_func, std::placeholders::_1, 2);
    f6(1);
}

除上述提到的函数外,std::function还可以接受类的静态函数、类的成员重载函数、仿函数,可以接受std::bind的返回值,这些内容在关于std::bind的讨论中涉及到,此处不再重复。

std::function类有一个默认的构造函数,使用默认的构造函数构造的对象不包含任何可调用函数,尝试对该对象进行函数调用操作,会抛出一个std::bad_function_call的异常。因此,若不知道某个std::function对象是否可以被调用,应该在调用前进行判断。

#include<iostream>
#include<functional>
 
int main()
{
    std::function<int(int)> f;
    if(f) // false, f not callable
        f(0);
    try {
        f(0); // throw std::bad_function_call
    }
    catch(std::bad_function_call &e) {
        std::cout << e.what() << std::endl;
    }
}

使用std::function 代替函数指针可以更加方便、安全地完成一些操作,如果std::function正符合你的需求,请使用它吧。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注