函数对象:
1.函数名
2.指向函数的指针
3.重载了()的类
函数名就是普通的函数,指向函数的指针会造成的一些问题是gdb、kdb的时候,调用栈会出现问题,因为这些调试工具跟踪的是函数名,用地址调用的时候符号表里面无法反应。使用重载了()的类对象的一个特点是可以使用额外的变量,例如构造对象的时候传入的私有成员数据。
函数符:
1.生成器:没有参数的函数符
2.一元函数:一个参数
3.二元参数:两个参数
谓词:返回bool值的一元函数
二元谓词:返回bool值的二元函数
使用重载了()的类的对象的一个好处是,需要调整值的时候,只要新创建一个对象就行而不用重新修改函数,例如,对于list的一个成员函数remove_if,参数是一个一元谓词,当返回值为true的时候,将节点删除,比如n > 100是条件,那么使用如下:
bool toobig(int n)
{
if (n > 100)
return true;
return false;
}
list<int> tmp;
tmp.remove_if(toobig);
下次若需要判断n > 200,就需要增加一个函数,若有频繁使用不同取舍值的场景,那么使用函数对象较好,每次创建新的对象就行了,如下:
template <typename T>
class TooBig
{
private:
T cutoff;
public:
TooBig(const T & t) : cutoff(t){}
bool operator()(const T & t){return t > cutoff;}
};
list<int>tmp;
tmp.remove_if(TooBig<int>(10));
STL预定义函数符:头文件functional,是一些模板类对象,定义这些是为了防止对每种类型都定义一个同样功能的函数,比如double的加法和int的加法,可以直接用plus<>模板类,使用如下:
#include <functional>
plus<double>add;
double tmp = add(1.1, 2.2); //plus<double>.operator()
所有内置算数运算符、关系运算符、逻辑运算符都有STL预定义的函数符
函数适配器:bind1st:用来制作适配器,将一个二元函数适配成一个一元函数,bind2nd用来替换的是第二个参数,如下:
void func2()
{
double arr1[] = {28, 29, 30, 35, 38, 59};
double arr2[] = {63, 65, 69, 75, 80, 99};
vector<double>gr8(arr1, arr1 + 6);
vector<double>m8(arr2, arr2 + 6);
/* 5个参数的transform,使用二元函数 */
vector<double>sum(6);
transform(gr8.begin(), gr8.end(), m8.begin(), sum.begin(), plus<double>());
for_each(sum.begin(), sum.end(), show);
cout << endl;
/* 使用bind1st提供适配器,将二元函数转换为一元函数 */
vector<double>prod(6);
transform(gr8.begin(), gr8.end(), prod.begin(), bind1st(multiplies<double>(), 2.5));
for_each(prod.begin(), prod.end(), show);
cout << endl;
}
C++11提供了lambda表达式,和python差不多