C++高阶笔记第四篇:STL-函数对象
一、函数对象
1.函数对象概念
概念:
- 重载函数调用操作符的类,其对象常称为函数对象
- 函数对象使用重载的()时,行为类似函数调用,也叫仿函数
本质:
函数对象(仿函数)是一个类,不是一个函数
2.函数对象使用
特点:
- 函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
- 函数对象超出普通函数的概念,函数对象可以有自己的状态(成员属性等...)
- 函数对象可以作为参数传递
示例:
//1.函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
//运算两个数的仿函数
class MyAdd
{
public:int operator()(int a, int b){return a + b;}
};
void test01()
{MyAdd Add;cout <<"10 + 20 = " << Add(10, 20) << endl;
}//2.函数对象超出普通函数的概念,函数对象可以有自己的状态(成员属性等...)//负责打印字符串的仿函数
class Myprint
{
public:Myprint(){this->count = 0;}void operator()(string print){cout << print << endl;this->count++;//每调用一次仿函数就++一次}int count;//可以有自己的状态
};
void test02()
{Myprint mp;mp("hello world");mp("hello world");mp("hello world");mp("hello world");mp("hello world");cout << "调用仿函数mp的次数:>" << mp.count << endl;
}//3.函数对象可以作为参数传递
void Doprint(Myprint& mp, string print)
{mp(print);
}
void test03()
{Myprint mp;Doprint(mp, "hello C++");//仿函数(函数对象)可以作为参数传递
}
int main()
{test01();test02();test03();return 0;
}
运行代码:
二、谓词
1.谓词概念
概念:
- 返回bool类型的仿函数称为谓词
- 如果operator()接收一个参数,那么叫做一元谓词
- 如果operator()接收两个参数,那么叫做二元谓词
比如:上一篇STL容器笔记set和map排序规则需要的就是谓词,需要两个参数比较返回bool判断所以是二元谓词
2.一元谓词
记住,只要见到函数需要_Pr _Pred就说明这个是谓词
示例:
//创建一元谓词
class GreaterFive
{
public://返回类型为bool,并且参数只有一个,就是一元谓词bool operator()(int val){return val > 5;//判断参数val是否大于5}
};
int main()
{vector<int> v;int i = 0;for (i = 0; i < 10; i++){v.push_back(i + 1);}//创建一个匿名的函数对象(仿函数)调用find_if//find_if是查找容器中是否有大于5的数,有就返回迭代器,没有就返回end()vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive());if (it == v.end()){cout << "没有大于5的数" << endl;}else{cout << *it << endl;}return 0;
}
代码运行:
总结:参数只有一个的谓词,称为一元谓词
3.二元谓词
示例:
class Compare
{
public://二元谓词bool operator()(int val1, int val2){return val1 > val2;}
};
int main()
{vector<int>v;int i = 0;for (i = 0; i < 5; i++){v.push_back(i + 1);}sort(v.begin(), v.end(), Compare());for (vector<int>::iterator it = v.begin(); it < v.end(); it++){cout << *it << " ";}cout << endl;return 0;
}
运行代码:
总结:参数有两个的谓词,称为二元谓词
三、内建函数对象
1.内建函数对象意义
概念:
- STL内建了一些函数对象
分类:
- 算术仿函数
- 关系仿函数
- 逻辑仿函数
用法:
- 这些仿函数所产生的对象,用法和一般函数完全相同
- 使用内建函数对象,需要引入头文件#include<functional>
2.算术仿函数
功能描述:
- 实现四则运算
- 其中negate是一元运算,其他都是二元运算
仿函数原型:
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> //取反仿函数
这里的算术仿函数太多了,我就挑一个一元和一个二元放入示例:
int main()
{//一元运算int x = 50;negate<int>neg;cout << neg(x) << endl;//-50//二元运算int a = 10;int b = 20;plus<int>add;cout << add(10, 20) << endl;//30return 0;
}
运算代码:
总结:使用内建函数对象时,需要引入头文件#include <functional>
3.关系仿函数
功能描述:
- 实现关系对比
仿函数原型:
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> //小于等于
这些都是谓词,是内建的谓词,实际上我们最常用的还是greater(大于)
原因:只要是排序算法函数或成员函数,默认的仿函数都是小于,也就是升序,我们只有在降序的时候才会使用大于仿函数,其他的基本不用
示例:
int main()
{vector<int>v;int i = 0;for (i = 0; i < 5; i++){v.push_back(i + 1);}//传一个匿名的内建函数对象大于sort(v.begin(), v.end(), greater<int>());for (vector<int>::iterator it = v.begin(); it < v.end(); it++){cout << *it << " ";}cout << endl;return 0;
}
运行代码:
总结:关系仿函数中最常用的就是greater<>大于
4.逻辑仿函数
功能描述:
- 实现逻辑运算
函数原型:
template<class T> bool logical_and <T> //逻辑与template<class T> bool logical_or <T> //逻辑或template<class T> bool logical_not <T> //逻辑异或
示例:
void printVector(vector<bool>&v)
{for (vector<bool>::iterator it = v.begin(); it < v.end(); it++){cout << *it << " ";}cout << endl;
}
int main()
{vector<bool>v1;v1.push_back(true);v1.push_back(false);v1.push_back(false);v1.push_back(true);v1.push_back(true);printVector(v1);//创建一个容器v2,将容器v1中的所有数据异或后存入v2vector<bool>v2;v2.resize(v1.size());//给v2的空间开辟为v1元素个大小空间//接下来是一个算法库的算法,后面笔记会学到//这个算法是指定一个区间,将这个区间拷贝到指定位置//并将这个区间的每个元素经过自己传入的逻辑取反的仿函数逻辑取反后插入v2容器transform(v1.begin(), v1.end(), v2.begin(), logical_not<bool>());printVector(v2);return 0;
}
代码运行:
总结:逻辑仿函数实际应用较少,了解即可
transform是算法库中的一种算法,是遍历算法,刚才使用时我们知道这个算法是将一个容器区间的元素插入一个指定位置,这个算法在下一篇的STL算法笔记中会介绍
STL函数对象笔记已学完