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正符合你的需求,请使用它吧。
本文由kedixa发表于个人博客,
转载请注明作者及出处。
本文链接:https://blog.kedixa.top/2017/cpp-std-function/