概念:
重载函数调用符号()的类,其对象常被称为函数对象
函数对象使用重载的()时,行为类似函数调用,也叫仿函数
本质:
函数对象(防函数)是一个类,不是一个函数
特点:
函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
函数对象可以有自己的状态,可以做一些状态记录工作
函数对象可以做为参数传递
#include
#include
#include
#include
#include
#include
using namespace std;
#define CEHUA 0
#define MEISHU 1
#define YANFA 2
//函数对象 防函数
class MyAdd {
public:
int operator()(int v1, int v2) {
return v1 + v2;
}
};
// 1. 函数对象在使用时,可以像普通函数一样,可以有参数传递,可以有返回值
void test01() {
MyAdd myAdd;
cout << myAdd(10, 20) << endl;
}
// 2. 函数对象可以有自己的状态,可以做简单的缓存
class MyPrint {
public:
void operator()(string text) {
cout << text << endl;
count++;
}
int count = 0;
void add() {
cout << "add" << endl;
}
};
void test02() {
MyPrint myPrint;
myPrint("hello world");
myPrint("西施很漂亮");
myPrint("西施很漂亮");
myPrint("西施很漂亮");
myPrint("西施很漂亮");
myPrint.add(); // 成员函数
cout << myPrint.count << endl;
}
// 3. 函数对象可以作为参数传递
void doPrint(MyPrint &myPrint, string text) {
myPrint(text);
}
void test03() {
MyPrint myPrint;
doPrint(myPrint, "西施很漂亮");
}
int main(int argc, char const *argv[]) {
test03();
return 0;
}
概念:
返回bool类型的防函数称为谓词
如果operator()接受一个参数,么叫一元谓词
如果operator()接受两个参数,么叫二元谓词
#include
#include
#include
#include
#include
using namespace std;
#define CEHUA 0
#define MEISHU 1
#define YANFA 2
// 一元谓词
class GreateFive {
public:
bool operator()(int val) {
return val > 5;
}
};
void test01() {
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
// 查找容器中有没有大于5的元素
vector<int>::iterator it = find_if(v.begin(), v.end(), GreateFive());
if (it == v.end()) {
cout << "没有找到" << endl;
}
else {
cout << "找到大于5的数字为:" << *it << endl;
}
}
int main(int argc, char const *argv[]) {
test01();
return 0;
}
#include
#include
#include
#include
#include
using namespace std;
#define CEHUA 0
#define MEISHU 1
#define YANFA 2
// 二元谓词
class myCompare {
public:
bool operator()(int val, int val2) {
return val > val2;
}
};
void test01() {
vector<int> v;
v.push_back(10);
v.push_back(30);
v.push_back(50);
v.push_back(40);
v.push_back(20);
sort(v.begin(), v.end());
for(vector<int>::iterator it = v.begin(); it != v.end(); it++){
cout << *it << " ";
}
cout << endl;
// 使用函数对象,排序规则为从大到小
sort(v.begin(), v.end(), myCompare());
for(vector<int>::iterator it = v.begin(); it != v.end(); it++){
cout << *it << " ";
}
cout << endl;
}
int main(int argc, char const *argv[]) {
test01();
return 0;
}
sort 源码
template<typename _RandomAccessIterator, typename _Compare>
_GLIBCXX20_CONSTEXPR
inline void
sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
_Compare __comp)
{
// concept requirements
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
_RandomAccessIterator>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
typename iterator_traits<_RandomAccessIterator>::value_type,
typename iterator_traits<_RandomAccessIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
std::__sort(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp));
}
template <typename _Compare>
struct _Iter_comp_iter
{
_Compare _M_comp;
explicit _GLIBCXX14_CONSTEXPR
_Iter_comp_iter(_Compare __comp)
: _M_comp(_GLIBCXX_MOVE(__comp))
{
}
template <typename _Iterator1, typename _Iterator2>
_GLIBCXX14_CONSTEXPR bool
operator()(_Iterator1 __it1, _Iterator2 __it2)
{
return bool(_M_comp(*__it1, *__it2));
}
};
template <typename _Compare>
_GLIBCXX14_CONSTEXPR inline _Iter_comp_iter<_Compare>
__iter_comp_iter(_Compare __comp)
{
return _Iter_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp));
}
可以看到sort 中需要的是_Iter_comp_iter,bool(_M_comp(*__it1, *__it2)) 需要的就是二元谓词
概念:
stl内建了一些函数对象
分类:
算术防函数
关系防函数
逻辑防函数
用法:
这些防函数所产生的对象,用法和一般函数完全相同
使用内建函数对象,需要引入头文件 #include
功能描述:
实现四则运算
其中negate是一元元算,其他都是二元元算
防函数原型:
template T plus(T a, T b) // 加法
template T minus(T a, T b) // 减法
template T multiply(T a, T b) // 乘法
template T divide(T a, T b) // 除法
template T mod(T a, T b) // 取模
template T negate(T a) // 取反
#include
#include
#include
#include
using namespace std;
#define CEHUA 0
#define MEISHU 1
#define YANFA 2
// 算术防函数
void test01() {
// negate 一元防函数 取反
negate<int> n;
cout << n(50) << endl;
// 二元防函数 加法
plus<int> p;
cout << p(10, 20) << endl;
plus<string> p2;
cout << p2("hello", "world") << endl;
// 减法
minus<int> m;
cout << m(10, 20) << endl;
}
int main(int argc, char const *argv[]) {
test01();
return 0;
}
防函数原型
template equal_to; // 等于
template not_equal_to; // 不等于
template greater; // 大于
template greater_equal; // 大于等于
template less; // 小于
template less_equal; // 小于等于
#include
#include
#include
#include
#include
using namespace std;
#define CEHUA 0
#define MEISHU 1
#define YANFA 2
// 关系防函数
class Person
{
public:
Person(string name, int age) : name(name), age(age) {}
string name;
int age;
// 大于 const 是必要的
bool operator>(const Person &p) const
{
return this->age > p.age;
}
};
void test01()
{
vector<int> v;
v.push_back(80);
v.push_back(20);
v.push_back(60);
v.push_back(40);
v.push_back(50);
// 大于
greater<int> g1;
// 使用内建函数对象 实现降序
sort(v.begin(), v.end(), g1);
for (auto it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
// 实现自定义数据类型 降序
vector<Person> vp;
vp.push_back(Person("西施", 20));
vp.push_back(Person("王昭君", 18));
vp.push_back(Person("杨玉环", 16));
vp.push_back(Person("貂蝉", 19));
vp.push_back(Person("小乔", 17));
sort(vp.begin(), vp.end(), greater<Person>());
for (auto it = vp.begin(); it != vp.end(); it++)
{
cout << "name: " << it->name << "\t age: " << it->age << endl;
}
}
int main(int argc, char const *argv[])
{
test01();
return 0;
}
函数原型:
template bool logical_and::operator()(const T& x, const T& y) const; // 逻辑与
template bool logical_or::operator()(const T& x, const T& y) const; // 逻辑或
template bool logical_not::operator()(const T& x) const; // 逻辑非
#include
#include
#include
#include
#include
using namespace std;
#define CEHUA 0
#define MEISHU 1
#define YANFA 2
// 逻辑防函数
void test01()
{
// 逻辑非
vector<bool> vb;
vb.push_back(true);
vb.push_back(false);
vb.push_back(true);
vb.push_back(false);
for(vector<bool>::iterator it = vb.begin(); it != vb.end(); it++){
cout << *it << " ";
}
cout << endl;
cout << "逻辑非" << endl;
vector<bool> vb2;
vb2.resize(vb.size());
transform(vb.begin(), vb.end(), vb2.begin(), logical_not<bool>());
for(vector<bool>::iterator it = vb2.begin(); it != vb2.end(); it++){
cout << *it << " ";
}
cout << endl;
}
int main(int argc, char const *argv[])
{
test01();
return 0;
}