本文最后更新于:2021年2月7日 下午
STL函数对象,即仿函数。
函数对象
- 重载函数调用操作符的类,其对象常称为函数对象
- 函数对象使用重载的()时,行为类似函数调用,也叫仿函数
函数对象本质上是一个类的对象,然后重载了(),看起来像一个函数调用,但实际上是一个类。
函数对象的使用
- 函数对象使用时可以像普通函数那样调用,可以有参数,可以由返回值,均可以通过重载()来实现。
- 函数对象不同于普通函数,因为其本质是一个类,通过类,函数对象可以拥有自身的状态,但是普通函数需要全局变量或者静态变量。
- 函数对象可以通过参数传递。
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
| class MyAdd { public:
MyAdd() { count = 0; } int operator()(int a,int b){ count++; return a + b; }
int operator()(int a, int b, int c) { count++; return a + b + c; }
int count; };
int myFunc(MyAdd& myadd, int a, int b) { return myadd(a, b); }
void test1() {
MyAdd myadd;
cout << myadd(1, 2) << endl; cout << myadd(1, 2, 3) << endl; cout << myadd(1, 2, -3) << endl;
cout << myFunc(myadd, 2, -3) << endl;
cout << myadd.count << endl;
}
|
谓词
- 返回bool类型的仿函数称为谓词
- 如果operator()接受一个参数,那么叫做一元谓词
- 如果operator()接受两个参数,那么叫做二元谓词
- 谓词在STL算法的调用中使用非常广泛,通过自定义谓词,可以使得STL算法适用于自定义数据类型,并且写法非常灵活。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Greater30 { public: bool operator()(int val) { return val > 30; } };
void test2() {
int num = 50;
if (Greater30()(num)) { cout << "num : "<<num<<" 大于30" << endl; }else cout << "num : " << num << " 小于30" << endl;
}
|
STL内建函数对象
使用内建函数对象,需要引入头文件 #include<functional>
这些仿函数所产生的对象,用法和一般函数完全相同。
算数仿函数
template<class T> T plus<T>
//加法仿函数
template<class T> T minus<T>
//减法仿函数
template<class T> T multiplies<T>
//乘法仿函数
template<class T> T divides<T>
//除法仿函数
template<class T> T modulus<T>
//取模仿函数
template<class T> T negate<T>
//取反仿函数
其中negate是一元运算,其他都是二元运算
1 2 3 4 5 6 7 8 9 10
| void test3() {
negate<int> neg; cout << neg(12) << endl;
plus<int> add;
cout << add(1, 23) << endl;
}
|
关系仿函数
template<class T> bool equal_to<T>
//等于
template<class T> bool not_equal_to<T>
//不等于
template<class T> bool greater<T>
//大于
template<class T> bool greater_equal<T>
//大于等于
template<class T> bool less<T>
//小于
template<class T> bool less_equal<T>
//小于等于
比较常用的是大于仿函数。
sort默认排序适用的是less仿函数,更改排序方式时,可以适用greater仿函数,不需要自己再实现。
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 39 40 41
| class MyCmp { public: bool operator()(int a, int b) { return a > b; } };
void PrintVector(vector<int> &v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) cout << *it << " "; cout << endl; }
void test4() {
vector<int> v; v.push_back(1); v.push_back(5); v.push_back(6); v.push_back(3); v.push_back(4); v.push_back(2);
sort(v.begin(),v.end()); PrintVector(v);
sort(v.begin(),v.end(),MyCmp()); PrintVector(v);
sort(v.begin(),v.end(),greater<int>()); PrintVector(v); greater<int> g; sort(v.begin(), v.end(), g); PrintVector(v);
}
|
- 值得注意的一点,
MyCmp()
以及greater<int>()
均为匿名对象。
- 实际上第三个参数等待的对象是一个谓词。
逻辑仿函数
template<class T> bool logical_and<T>
//逻辑与
template<class T> bool logical_or<T>
//逻辑或
template<class T> bool logical_not<T>
//逻辑非
实际使用较少。