目录
1.function包装器
C++是面向对象的一门语言,因此为了封装函数,也出现了仿函数,便于传参使用。C++11新增了lambda表达式,进一步提高编程者的效率。但是,C语言的函数指针、C++98的仿函数、C++11的lambda表达式都存在一些弊端:
函数指针void(*pf)() | 类型复杂,不便于阅读书写 |
仿函数 | 不同的类,类型不同 |
lambda表达式 | 语法层没有返回类型 |
比如这部分代,有一个函数模板,分别用不同的形式去传参,模板实例化的useF是有三种
template<class F,class T>
T useF(F fun, T x)
{
static int count = 0;
cout << "count:" << ++count << endl;
cout << "------------" << endl;
return fun(x);
}
//回调函数
double f(double i)
{
return i / 2;
}
//仿函数
struct Functor
{
double operator()(double d)
{
return d / 3;
}
};
int main()
{
//函数指针
cout << useF(f, 11.11) << endl;
//仿函数
cout << useF(Functor(), 11.11) << endl;
//lambda表达式
cout << useF([](double d)->double {return d / 4; }, 11.11) << endl;
return 0;
}
C++11为了统一类型,对这一层进行了封装,即包装器。
C++的头文件中存在类模板
模板参数说明:
Ret: 被调用函数的返回类型
Args…:被调用函数的形参
有了包装器,对上面的语法修改:
int main()
{
//函数指针
function<double(double)> func1 = f;//这一层用包装器
cout << useF(func1, 11.11) << endl;//此时useF的第一个参数都是function类型
//仿函数
function<double(double)> func2 = Functor();
cout << useF(func2, 11.11) << endl;
//lambda表达式
function<double(double)> func3 = [](double d)->double {return d / 4; };
cout << useF(func3, 11.11) << endl;
return 0;
}
特殊情况用包装器封装类中的成员函数。
int main()
{
// 普通函数
function<int(int, int)> fc1 = f;
cout << fc1(1, 1) << endl;
// 静态成员函数
function<int(int, int)> fc2 = Plus::plusi;
cout << fc2(1, 1) << endl;
// 因为this指针导致参数不匹配,非静态成员函数需要对象的指针或者对象去进行调用
/*第一种写法:
Plus plus;
function<double(Plus*, double, double)> fc3 = &Plus::plusd;
cout << fc3(&plus, 1, 1) << endl;*/
//第二种写法
function<double(Plus, double, double)> fc3 = &Plus::plusd;
cout << fc3(Plus(), 1, 1) << endl;
return 0;
}
2.bind包装器
是定义在C++头文件中的函数模板
使用bind一般可以调整函数参数的顺序或者调整个数。 调整个数的场景居多,拿这个举例。
实现的大致方法是用特定的顺序绑定参数。
在C++的头文件中封装了一个命名空间
_1、_2、_3·····就是用来绑定参数的标识符。
class Plus
{
public:
static int plusi(int a, int b)
{
return a - b;
}
double plusd(double a, double b)
{
return a - b;
}
};
int main()
{
function<double(double, double)> fc4 = bind(&Plus::plusd, Plus(), placeholders::_1, placeholders::_2);
cout << fc4(2, 3) << endl;
function<double(double)> fc5 = bind(&Plus::plusd, Plus(), placeholders::_1, 20);
cout << fc5(2) << endl;
return 0;
}
bind的第一个参数,是函数名,这里由于是成员函数,要加&取地址符(语法规定)。剩下的参数都是属于参数包的,由于this指针,这里第二个参数对应plusd隐藏的第一个参数。_1绑定plusd的a,_2绑定b。
也可以只绑定a,就是用_1来绑定,语法上要对应在正确的位置。 调用时,因为部分参数已经被绑定,因此明显减少了需要传递的参数: