就是重载了()操作符的类,就是用于需要函数作为参数的函数
class Linear { private: double slope; double y0; public: Linear(double sl_ = 1, double y_ = 0): slope(sl_), y0(y_) {} double operator()(double x) {return y0 + slope * x; } };
1.一个generator(生成器)可以是一个没有参数的仿函数 2.带有一个参数的仿函数叫做unary function(一元函数) 3.带有两个参数的仿函数叫做binary function(二元函数)
1.返回一个bool值的unary function叫做predicate(谓词) 2.返回一个bool值的binary function叫做binary predicate(二元谓词)
templateFunction for_each(InputIterator first, InputIterator last, Function f); void ShowReview(const Review &);
list.remove_if(func)---对list中的每个元素都执行func;如果func返回true,则删除list中对应的元素,如果func返回false,则保留list中对应的元素。
定义的头文件:functional 操作符和伪函数等效
Operator | Functor Equivalent |
---|---|
+ | plus |
- | minus |
* | multiplies |
/ | divides |
% | modulus |
- | negate |
== | equal_to |
!= | not_equal_to |
> | greater |
< | less |
>= | greater_equal |
<= | less_equal |
&& | logical_and |
|| | logical_or |
! | logical_not |
举例:transform()的两个版本
transform(gr8.begin(), gr8.end(), out, sqrt); //第一、二个参数是一个迭代器范围,第三个参数是指定复制结果位置的迭代器,第四个参数是应用于范围中每个元素的仿函数。 transform(gr8.begin(), gr8.end(), m8.begin(), out, mean); //第一、二个参数是一个迭代器范围,第三个参数指向第二个范围的开头,第四个参数是指定复制结果位置的迭代器,第五个参数是应用于范围中每个元素的仿函数。
上面的所有预定义的仿函数都是适配器。
adaptable generators, adaptable unary functions, adaptable binary functions,adaptable predicates, adaptable binary predicates
在将可使用的仿函数(必须是可适应的)作为参数传递时,如果该函数有两个形参,但是将该函数作为参数的函数只能提供一个参数,这种情况该如何处理? 此时需要一个函数适配器将 可适应的二元仿函数 转换为可适应的一元仿函数。
STL提供了binder1st和binder2nd类,它可以将可适应的二元函数转换为可适应的一元函数
binder1st(f2, val) f1; f1(x);//等价于f2(val,x); //bind1st函数 bind1st(multiplies(), 2.5)//返回一个binder1st对象
举例:要给列表中的每个元素都乘以2.5.
代码
/* Project name : __26Function_Objects Last modified Date: 2022年4月11日17点09分 Last Version: V1.0 Descriptions: 仿函数 */ /* 仿函数:就是重载了()操作符的类,就是用于需要函数作为参数的函数 格式: class Linear { private: double slope; double y0; public: Linear(double sl_ = 1, double y_ = 0): slope(sl_), y0(y_) {} double operator()(double x) {return y0 + slope * x; } }; 仿函数概念: 1.一个generator(生成器)可以是一个没有参数的仿函数 2.带有一个参数的仿函数叫做unary function(一元函数) 3.带有两个参数的仿函数叫做binary function(二元函数) 仿函数概念改进: 1.返回一个bool值的unary function叫做predicate(谓词) 2.返回一个bool值的binary function叫做binary predicate(二元谓词) 仿函数举例: templateFunction for_each(InputIterator first, InputIterator last, Function f); void ShowReview(const Review &); list.remove_if(func)---对list中的每个元素都执行func;如果func返回true,则删除list中对应的元素,如果func返回false,则保留list中对应的元素。 预定义的仿函数: 定义的头文件:functional 操作符和伪函数等效: Operator Functor Equivalent + plus - minus * multiplies / divides % modulus - negate == equal_to != not_equal_to > greater < less >= greater_equal <= less_equal && logical_and || logical_or ! logical_not 举例:transform()的两个版本 transform(gr8.begin(), gr8.end(), out, sqrt); //第一、二个参数是一个迭代器范围,第三个参数是指定复制结果位置的迭代器,第四个参数是应用于范围中每个元素的伪函数。 transform(gr8.begin(), gr8.end(), m8.begin(), out, mean); //第一、二个参数是一个迭代器范围,第三个参数指向第二个范围的开头,第四个参数是指定复制结果位置的迭代器,第五个参数是应用于范围中每个元素的伪函数。 可适应的仿函数和函数适配器 上面的所有预定义的仿函数都是适配器。 有五种适配器: adaptable generators, adaptable unary functions, adaptable binary functions, adaptable predicates, adaptable binary predicates 解决的问题: 在将可使用的仿函数(必须是可适应的)作为参数传递时,如果该函数有两个形参,但是将该函数作为参数的函数只能提供一个参数,这种情况该如何处理? 此时需要一个函数适配器将 可适应的二元仿函数 转换为可适应的一元仿函数。 binder1st和binder2nd类 STL提供了binder1st和binder2nd类,它可以将可适应的二元函数转换为可适应的一元函数 binder1st(f2, val) f1; f1(x);//等价于f2(val,x); //bind1st函数 bind1st(multiplies (), 2.5)//返回一个binder1st对象 举例:要给列表中的每个元素都乘以2.5. */ #include #include #include
#include #include #include /* TooBig也可以是这个格式: 首先定义函数: template bool tooBig(const T & val, const T & lim) { return val > lim; } 然后定义仿函数类使用上述函数: template class TooBig2 { private: T cutoff; public: TooBig2(const T & t) : cutoff(t) {} bool operator()(const T & v) { return tooBig (v, cutoff); } }; */ template // functor class defines operator()() class TooBig { private: T cutoff; public: TooBig(const T& t) : cutoff(t) {} bool operator()(const T& v) { return v > cutoff; } }; void outint(int n) { std::cout << n << " "; } void Show(double); const int LIM = 6; int main() { using namespace std; TooBig f100(100); // limit = 100 int vals[10] = { 50, 100, 90, 180, 60, 210, 415, 88, 188, 201 }; list yadayada(vals, vals + 10); // range constructor list etcetera(vals, vals + 10); // C++11 can use the following instead,下面这个是初始化列表 // list yadayada = {50, 100, 90, 180, 60, 210, 415, 88, 188, 201}; // list etcetera {50, 100, 90, 180, 60, 210, 415, 88, 188, 201}; cout << "functor*********************************************************" << endl; cout << "Original lists:\n"; for_each(yadayada.begin(), yadayada.end(), outint); cout << endl; for_each(etcetera.begin(), etcetera.end(), outint); cout << endl; yadayada.remove_if(f100); // use a named function object etcetera.remove_if(TooBig (200)); // construct a function object cout << "Trimmed lists:\n"; for_each(yadayada.begin(), yadayada.end(), outint); cout << endl; for_each(etcetera.begin(), etcetera.end(), outint); cout << endl; cout << "Adaptable Functors and Function Adapters**************************" << endl; double arr1[LIM] = { 28, 29, 30, 35, 38, 59 }; double arr2[LIM] = { 63, 65, 69, 75, 80, 99 }; vector gr8(arr1, arr1 + LIM); vector m8(arr2, arr2 + LIM); cout.setf(ios_base::fixed); cout.precision(1); cout << "gr8:\t"; for_each(gr8.begin(), gr8.end(), Show); cout << endl; cout << "m8: \t"; for_each(m8.begin(), m8.end(), Show); cout << endl; vector sum(LIM); transform(gr8.begin(), gr8.end(), m8.begin(), sum.begin(), plus ()); cout << "sum:\t"; for_each(sum.begin(), sum.end(), Show); cout << endl; vector prod(LIM); transform(gr8.begin(), gr8.end(), prod.begin(), bind1st(multiplies (), 2.5)); cout << "prod:\t"; for_each(prod.begin(), prod.end(), Show); cout << endl; return 0; } void Show(double v) { std::cout.width(6); std::cout << v << ' '; }
运行结果:
functor********************************************************* Original lists: 50 100 90 180 60 210 415 88 188 201 50 100 90 180 60 210 415 88 188 201 Trimmed lists: 50 100 90 60 88 50 100 90 180 60 88 188 Adaptable Functors and Function Adapters************************** gr8: 28.0 29.0 30.0 35.0 38.0 59.0 m8: 63.0 65.0 69.0 75.0 80.0 99.0 sum: 91.0 94.0 99.0 110.0 118.0 158.0 prod: 70.0 72.5 75.0 87.5 95.0 147.5 D:\Prj\_C++Self\_24Function_Objects\Debug\_24Function_Objects.exe (进程 12252)已退出,代码为 0。 要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。 按任意键关闭此窗口. . .