C++11:包装器
目录
1.function包装器
2.bind包装器
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来绑定,语法上要对应在正确的位置。 调用时,因为部分参数已经被绑定,因此明显减少了需要传递的参数: