函数对象在C++编程中尤为重要,它可以帮助我们实现STL库中的函数按照自己的方法来实现功能,以及自定义数据结构的排序、查找等功能。
1 概念
函数对象是重载函数调用操作符的类的对象,也叫仿函数
函数对象可以有参数和返回值,可以作为参数传递
以下代码是一个仿函数实例,可以通过重载小括号实现两个数的相加。当然,不仅可以实现加法功能,四则运算,排序,输出打印功能均可实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class FunctorAdd {public : int operator () (int v1, int v2) { this ->count += 1 ; return v1 + v2; } int count; }; int main () { FunctorAdd add; cout << add (10 , 10 ) << endl; }
上述代码还可以发现,如果在仿函数类中设置一个能够记录状态的变量(本例中的count),我们可以根据需求记录函数对象的状态。
仿函数的写法非常的灵活,也可以作为参数进行传递。如下面这段代码。doAdd()函数实现的功能即为两个数的相加。运行结果为35.
1 2 3 4 5 6 7 8 int doAdd (FunctorAdd func, int v1, int v2) { return func (v1, v2); } int main () { FunctorAdd func; cout << doAdd (func,12 , 23 ); }
2 谓词
返回类型为bool的仿函数称为谓词
operator()接受一个参数称为一元谓词
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class FunctorGF {public : int operator () (int val) { return val > 5 ; } }; int main () { vector<int >v = { 1 ,34 ,2 ,3 ,43 ,34 ,23 ,43 ,2 ,34 ,343 ,423 ,42 ,4 }; vector<int >::iterator iter; iter=find_if (v.begin (), v.end (), FunctorGF ()); if (iter == v.end ()) { cout << "not find" << endl; } else cout << "at least a number is greater than 5" << endl; }
二元谓词最经典的案例就是排序了。STL中很多容器都可以加入自定义的排序规则。不妨写一个set容器的降序排列的实现方法作为二元谓词的案例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class FunctorCmp { public : int operator () (int v1,int v2) const { return v1 > v2; } }; int main () { set<int ,FunctorCmp>s = { 1 ,34 ,2 ,3 ,43 ,34 ,23 ,43 ,2 ,34 ,343 ,423 ,42 ,4 }; set<int >::iterator iter; for (iter = s.begin ();iter != s.end ();iter++) cout << *iter << " " ; }
输出为:
423 343 43 42 34 23 4 3 2 1
3 内建函数对象
STL内建了一些函数对象,整体分为关系仿函数、逻辑仿函数和算术仿函数三类。这些仿函数所产生的对象用法和一般函数完全相同,但使用时需要引入头文件
#include <functional>
3.1 关系仿函数
template bool equal_to //等于
template bool not_ equal_to //不等于
template bool greater //大于
template bool greater_equal //大于等于
template bool less //小于
template bool less_equal //小于等于
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 int main () { vector<int > test; for (int i = 0 ;i < 10 ;i++) { test.push_back (i * 3 ); } sort (test.begin (), test.end (), greater <int >()); cout << "descending order:" ; for (int i = 0 ;i < 10 ;i++) { cout << test[i] << " " ; } cout << endl; sort (test.begin (), test.end (), less <int >()); cout << "increasing order:" ; for (int i = 0 ;i < 10 ;i++) { cout << test[i] << " " ; } }
输出结果
descending order:27 24 21 18 15 12 9 6 3 0
increasing order:0 3 6 9 12 15 18 21 24 27
3.2 逻辑仿函数
实现与或非的逻辑运算
template bool logical_and //逻辑与
template bool logical_or //逻辑或
template bool logical_not //逻辑非
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 int main () { vector<bool > v1 = { true , false , true , false , true }; vector<bool > v2 = { true , true , false , false , true }; vector<bool > res; res.resize (v1.size ()); cout << "raw data v1: " ; for (int i = 0 ;i < 5 ;i++) { cout << v1[i] << " " ; } cout << endl; cout << "raw data v2: " ; for (int i = 0 ;i < 5 ;i++) { cout << v2[i] << " " ; } cout << endl; cout << "logical not data: " ; cout << endl; transform (v1.begin (), v1.end (), res.begin (), logical_not <bool >()); for (int i = 0 ;i < 5 ;i++) { cout << " not " << v1[i] << " = " << res[i] << endl; } cout << "logical and data: " ; cout << endl; transform (v1.begin (), v1.end (), v2.begin (), res.begin (), logical_and <bool >()); for (int i = 0 ;i < 5 ;i++) { cout <<v1[i] << " and " << v2[i] << " = " << res[i] << endl; } cout << endl; cout << "logical or data: " ; cout << endl; transform (v1.begin (), v1.end (), v2.begin (), res.begin (), logical_or <bool >()); for (int i = 0 ;i < 5 ;i++) { cout << v1[i] << " or " << v2[i] << " = " <<res[i] << endl; } }
输出结果:
raw data v1: 1 0 1 0 1
raw data v2: 1 1 0 0 1
logical not data:
not 1 = 0
not 0 = 1
not 1 = 0
not 0 = 1
not 1 = 0
logical and data:
1 and 1 = 1
0 and 1 = 0
1 and 0 = 0
0 and 0 = 0
1 and 1 = 1
logical or data:
1 or 1 = 1
0 or 1 = 1
1 or 0 = 1
0 or 0 = 0
1 or 1 = 1
3.3 算术仿函数
template T plus //加法仿函数
template T minus //减法仿函数
template T multiplies //乘法仿函数
template T divides //除法仿函数
template T negate //取反仿函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class FunctorCmp { public : int operator () (int v1,int v2) const { return v1 > v2; } }; int main () { plus<int >plus; minus<int >min; multiplies<int >mul; divides<int >div; negate<int >neg; cout << "plus functor: 13+14=" << plus (13 , 14 ) << endl; cout << "minus functor: 13-14=" << min (13 , 14 ) << endl; cout << "multiplies functor: 13*14=" << mul (13 , 14 ) << endl; cout << "divides functor: 28/14=" << div (28 , 14 ) << endl; cout << "negate functor: -20=" << neg (20 ) << endl; }
输出结果:
plus functor: 13+14=27
minus functor: 13-14=-1
multiplies functor: 13*14=182
divides functor: 28/14=2
negate functor: -20=-20