函数对象和谓词定义
函数对象:
重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类
似函数的对象。一个类对象,表现出一个函数的特征,就是通过“对象名+(参数列表)”的方式
使用一个类对象,如果没有上下文,完全可以把它看作一个函数对待。
这是通过重载类的 operator()来实现的。
“在标准库中,函数对象被广泛地使用以获得弹性”,标准库中的很多算法都可以使用函数
对象或者函数来作为自定的回调行为;
谓词:
一元函数对象:函数参数 1 个;
二元函数对象:函数参数 2 个;
一元谓词 函数参数 1 个,函数返回值是 bool 类型,可以作为一个判断式
谓词可以使一个仿函数,也可以是一个回调函数。
二元谓词 函数参数 2 个,函数返回值是 bool 类型
一元谓词函数举例如下
1,判断给出的 string 对象的长度是否小于 6
bool GT6(const string &s)
{
return s.size() >= 6;
}
2,判断给出的 int 是否在 3 到 8 之间
bool Compare( int i )
{
return ( i >= 3 && i <= 8 );
}
二元谓词举例如下
1,比较两个 string 对象,返回一个 bool 值,指出第一个 string 是否比第二个短
bool isShorter(const string &s1, const string &s2)
{
return s1.size() < s2.size();
}
一元函数对象案例:
//1 普通类 重载 函数调用操作符
template <typename T>
void FuncShowElemt(T &t) //普通函数 不能像 仿函数那样记录状态
{
cout << t << " ";
};
void showChar(char &t)
{
cout << t << " ";
}
//函数模板 重载 函数调用操作符
template <typename T>
class ShowElemt
{
public:
ShowElemt()
{
n = 0;
}
void operator()(T &t)
{
n++;
cout << t << " ";
}
void printCount()
{
cout << n << endl;
}
public:
int n;
};
//1 函数对象 基本使用
void main11()
{
int a = 100;
FuncShowElemt<int>(a); //普通的函数调用
ShowElemt<int> showElemt; //函数对象
showElemt(a); //函数对象调用
}
一元谓词案例
//1 元谓词 例子
template <typename T>
class Isdiv
{
public:
Isdiv(const T &divisor) //
{
this->divisor = divisor;
}
bool operator()(T &t)
{
return (t%divisor == 0);
}
protected:
private:
T divisor;
};
void main13()
{
vector<int> v2;
for (int i=10; i<33; i++)
{
v2.push_back(i);
}
vector<int>::iterator it;
int a = 4;
Isdiv<int> mydiv(a);
// _InIt find_if(_InIt _First, _InIt _Last, _Pr _Pred) //返回的是迭代器
it = find_if(v2.begin(), v2.end(), Isdiv<int>(4));
if (it != v2.end())
{
cout << "第一个被 4 整除的数是:" << *it << endl;
} }
二元函数对象案例
template <typename T>
struct SumAdd
{
T operator()(T &t1, T &t2)
{
return t1 + t2;
}
};
template <typename T>
void printE(T &t)
{
for (vector<int>::iterator it = t.begin(); it!=t.end(); it++ )
{
cout << *it << " ";
} }
void printVector(vector<int> &v)
{
for (vector<int>::iterator it = v.begin(); it!=v.end(); it++ )
{
cout << *it << " ";
} }
void main14()
{
vector<int> v1, v2 ;
vector<int> v3;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v2.push_back(4);
v2.push_back(5);
v2.push_back(6);
v3.resize(10);
//transform(v1.begin(), v1.end(), v2.begin(),v3.begin(), SumAdd<int>());
/*
template<class _InIt1,
class _InIt2,
class _OutIt,
class _Fn2> inline
_OutIt transform(_InIt1 _First1, _InIt1 _Last1,
_InIt2 _First2, _OutIt _Dest, _Fn2 _Func)
*/
vector<int>::iterator it = transform(v1.begin(), v1.end(), v2.begin(),v3.begin(),
SumAdd<int>());
cout << *it << endl;
printE(v3);
}
二元谓词案例
void current(int &v)
{
cout << v << " ";
}
bool MyCompare(const int &a, const int &b)
{
return a < b;
}
void main15()
{
vector<int> v(10);
for (int i=0; i<10; i++)
{
v[i] = rand() % 100;
}
for_each(v.begin(), v.end(), current);
printf("\n");
sort(v.begin(), v.end(), MyCompare );
printf("\n");
for (int i=0; i<10; i++)
{
printf("%d ", v[i]);
}
printf("\n");
}
综合案例:
#include<iostream>
using namespace std;
#include "list"
#include "vector"
#include "string"
#include "algorithm"
#include "set"
#include "functional"
//函数对象:类重载了()操作符 这种类的对象
template <typename T>
class ShowElem
{
public:
ShowElem()
{
n = 0;
}
void operator()(T& t)
{
n++;
//printN();
cout << t << endl;
}
void printN()
{
cout << "n:" << n << endl;
}
private:
int n;
};
template <typename T>
void FuncShow(T &t)
{
cout << t << endl;
}
//普通函数
void FuncShow2(int &t)
{
cout << t << " ";
}
//函数对象和普通函数的区别
void main01()
{
int a = 10;
ShowElem<int> show;
show(a); //类对象的()调用很像函数的调用 又称为仿函数
//普通函数与仿函数的区别
FuncShow<int>(a);
FuncShow2(a);
}
//函数对象的好处:函数对象是属于类对象的,能突破函数的概念,保持调用的状态
//函数对象的好处:
//for_each算法中,函数对象做函数参数
//for_each算法中,函数对象做返回值
void main02()
{
vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(5);
for_each(v.begin(), v.end(),ShowElem<int>()); //匿名函数对象
for_each(v.begin(), v.end(), FuncShow2); //FuncShow2是回调函数的入口地址 谁使用for_each函数谁提供入口地址
ShowElem<int> show;
//函数对象做函数参数
//for_each算法的 函数对象的传递 是值传递,不是引用传递 需要用show接返回值
cout << "通过for_each函数的返回值查看调用的次数" << endl;
show = for_each(v.begin(), v.end(), show);
show.printN();
//要点:分清楚STL返回值是迭代器还是谓词(函数对象)是STL算法入门的重点
}
template <typename T>
class ISDiv
{
public:
ISDiv(const T &divs)
{
this->div = divs;
}
//一元谓词
bool operator()(T &t)
{
return (t%div == 0);
}
private:
T div;
};
void main03()
{
vector<int> v;
for (int i = 10; i < 30;i++)
{
v.push_back(i);
}
int a = 4;
ISDiv<int> MyDir(a);
//find_if(v.begin(),v.end(),MyDir);
vector<int>::iterator it;
it = find_if(v.begin(), v.end(), ISDiv<int>(4));
//find_if返回的是一个迭代器
if (it==v.end())
{
cout << "容器中没有值是4的倍数" << endl;
}
else
{
cout << "第一个被4整除的数是:" << *it << endl;
}
}
//二元函数对象
template <typename T>
class SumAdd
{
public:
T operator()(T &t1, T &t2)
{
return t1 + t2;
}
};
void main04()
{
//v3=v1+v2
vector<int> v1, v2, v3;
v1.push_back(1);
v1.push_back(3);
v1.push_back(5);
v2.push_back(2);
v2.push_back(4);
v2.push_back(6);
v3.resize(10);
//v1.begin() + v2.begin() 赋值给v3.begin开始的容器,以SumAdd的方式
transform(v1.begin(), v1.end() , v2.begin(), v3.begin() ,SumAdd<int>());
//transform把运算结果的迭代器的地址返回出来
for (vector<int>::iterator it = v3.begin();it != v3.end();it++)
{
cout << *it << " ";
}
cout << endl;
for_each(v3.begin(), v3.end(), FuncShow2); //FuncShow2回调函数
}
//二元谓词
bool MyCompare(const int &a, const int &b)
{
return a < b; //从小到大排序
}
void main05()
{
vector<int> v(10);
for (int i = 0; i < 10; i++)
{
int tmp = rand() % 100;
v[i] = tmp;
}
for (vector<int>::iterator it = v.begin();it != v.end();it++)
{
cout << *it << " ";
}
cout << endl;
//使用for_each函数遍历容器
for_each(v.begin(), v.end(), FuncShow2); //FuncShow2回调函数
cout << endl;
//排序算法
sort(v.begin(), v.end(), MyCompare); / /提供二元谓词
for_each(v.begin(), v.end(), FuncShow2); //FuncShow2回调函数
cout << endl;
}
void main()
{
//main01();
//main02();
//main03();//一元函数和一元谓词
//main04();//二元函数和二元谓词
main05();
system("pause");
}