目录
一、c++可调用对象--std::function
- 函数 函数又包含普通函数、类的静态与非静态成员函数。
- 函数指针
- 仿函数
- lambda表达式
- bind对象 其实是绑定前四种。
而上面5类对象,有一个统一的方式保存,那就是转换为std::function对象,实现类型消除机制。以前是用函数指针。
std::function就是一个对象包装器、类模板,取代函数指针:
# include <functional>
std::function<函数类型>
场景:实现函数回调。因为它可以延迟函数执行,特别适用作为回调函数。
二、std::bind--通用的函数适配器
std::bind接收一个可调用对象,生成一个新的可调用对象。
作用:
- 将可调用对象和其参数绑定成一个仿函数
- 设置默认参数,减少入参
一般形式:
auto newCallable = bind(callable, arg_list);
对于类成员函数bind需要传入对象地址,因为对象的成员函数需要this指针。函数参数std::placeholders(占位符)表示,默认参数直接写值。
场景:在绑定类非静态成员函数时特别有用。当然,你也可以用C语言指针的方式实现(作为一个C++程序员,你好意思么,嘿嘿)。或者其他可调用对象你想减少入参会使用bind。
三、实际举例
看代码:
#include <iostream>
#include <functional>
using namespace std;
// 声明一个模板
typedef std::function<int(int, int)> Functional;
// 普通函数
int AliFunc(int a, int b)
{
return a;
}
// 类的成员函数和类的静态成员函数
class AliTest {
public:
int Func(int a, int b)
{
return a;
}
static int SFunc(int a, int b)
{
return a;
}
};
// lambda表达式
auto lambda = [](int a, int b) -> int { return a; };
// functor仿函数(也叫函数对象)
class Functor {
public:
int operator()(int a, int b)
{
return a;
}
};
int main()
{
// 封装普通函数
Functional obj = AliFunc;
int res = obj(0, 0);
cout << "normal function : " << res << endl;
// 封装类的成员函数和static成员函数
AliTest t;
auto obj2 = std::bind(&AliTest::Func, &t, placeholders::_1, 666);
res = obj2(1);
cout << "member function : " << res << endl;
obj = AliTest::SFunc;
res = obj(2, 2);
cout << "static member function : " << res << endl;
// 封装lambda表达式
obj = lambda;
res = obj(3, 3);
cout << "lambda expression : " << res << endl;
// 封装仿函数
Functor functorObj;
obj = functorObj;
res = obj(4, 4);
cout << "functor : " << res << endl;
return 0;
}
输出结果:
normal function : 0
member function : 1
static member function : 2
lambda expression : 3
functor : 4
可见,std::function可以封装任何可调用对象,直接赋值即可。
另外,std::bind可以绑定任何可调用对象,类成员函数需要传入类对象地址。这里没举例别的,没必要都一样,绑定其他可调用对象只是少了类对象地址这个参数。