可调用对象(callable objects)有如下几种定义
- 是一个函数指针
- 是一个具有operator()成员函数的类对象(仿函数)
- 是一个可被转换为函数指针的类对象
- 是一个类成员(函数)指针
void func(void)
{
//.....
}
struct Foo
{
void operator()void
{
//...
}
};
struct Bar
{
using fr_t = void(*)(void);
static void func(void)
{
//....
}
operator fr_t(void)
{
return func;
}
};
struct A
{
int a_;
void mem_func(void)
{
//...
}
};
int main()
{
void(* func_ptr)(void) = &func;
func_ptr();//函数指针
Foo foo;
foo();//仿函数
Bar bar;
bar();//可被转化为函数指针的类对象
void (A::*mem_func_ptr)(void) = &A::*mem_obj_ptr;//类成员函数指针
int A::*mem_obj_ptr = &A::a_;//类成员指针
A aa;
(aa.*mem_func_ptr)();
aa.*mem_obj_ptr = 123;
C++11通过提供std::function和std::bind统一了可调用对象的各种操作
std::function -----------可调用对象包装器
std::function是一个类模板,可以容纳除了类成员(函数)指针之外的所有可调用对象。通过指定它的模板参数,它可以用统一的方法处理函数、函数对象、函数指针,并允许保存和延迟释放它们。std::function对象是对C++中现有的可调用实体的一种类型安全的包裹(我们知道像函数指针这类可调用实体,是类型不安全的)。通常std::function是一个函数对象类,它包装其它任意的函数对象,被包装的函数对象具有类型为T1, …,TN的N个参数,并且返回一个可转换到R类型的值。std::function使用 模板转换构造函数接收被包装的函数对象;特别是,闭包类型可以隐式地转换为std::function。
最简单的可以理解为:
通过std::function对C++中各种可调用实体(普通函数、Lambda表达式、函数指针、以及其它函数对象等)的封装,形成一个新的可调用的std::function对象;让我们不再纠结那么多的可调用实体。
std::function可以取代函数指针的作用。因为它可以保存函数延迟执行,所以比较适合做回调函数。代码如下:
/********回调函数的实现***************************/
class A
{
std::function<void()> callback_;//返回void不接受任何参数
public:
A(const std::function<void()>& f)
:callback_(f){}
void notify(void)
{
callback_();
}
};
class Foo
{
public:
void operator()(void)
{
cout<<__FUNCTION__<<endl;
}
};
int main()
{
Foo foo;
A aa(foo);
aa.notify();
return 0;
}
作为参数传递的应用:
void call_when_even(int x, const std::function<void(int)> &f)
{
if(!(x & 1))
{
f(x);
}
}
void output(int x)
{
cout<< x <<" ";
}