有些功能实现的代码,会不断的在不同的成员函数中用到,但是又不好将这些代码独立出来成为一个类的一个成员函数。但是又很想复用这些代码。
举例
假设我们现在有一个数组,数组中存有任意数量的数字,我们希望能够统计出这个数组中大于 10 的数字的数量:
//https://blog.csdn.net/K346K346/article/details/82818801
#include
using namespace std;
int RecallFunc(int *start, int *end, bool (*pf)(int))//函数指针当做参数
{
int count=0;
for(int *i=start;i!=end+1;i++)
{
count = pf(*i) ? count+1 : count;
}
return count;
}
bool IsGreaterThanTen(int num)
{
return num>10 ? true : false;
}
int main()
{
int a[5] = {10,100,11,5,19};
int result = RecallFunc(a,a+4,IsGreaterThanTen);
cout<<result<<endl;
return 0;
}
RecallFunc()
函数的第三个参数是一个函数指针,用于外部调用,而 IsGreaterThanTen()
函数通常也是外部已经定义好的,它只接受一个参数的函数。如果此时希望将判定的阈值也作为一个变量传入,变为如下函数就不可行了:
bool IsGreaterThanThreshold(int num, int threshold)
{
return num>threshold ? true : false;
}
虽然这个函数看起来比前面一个版本更具有一般性,但是它不能满足已经定义好的函数指针参数的要求,因为函数指针参数的类型是bool (*)(int)
,与函数bool IsGreaterThanThreshold(int num, int threshold)
的类型不相符。如果一定要完成这个任务,按照以往的经验,我们可以考虑如下可能途径:
“函数对象”:一种具有函数性质的对象(是类 而不是普通的函数)。为了能够“行为类似函数”,其类别定义中必须自定义(或说改写,重载)function call运算子(operator())
。拥有这样的运算子后,我们就可以在仿函数的对象后面加上一对小括号,以此调用仿函数所定义的operator()。
特点:
STL仿函数的分类:
template <class Arg, class Result>
struct unary_function {
typedef Arg argument_type; // 参数类型别名
typedef Result result_type; // 返回值类型别名
};
举例:
//2.使用1元仿函数
class CopyClass1Param :public unary_function<int, bool>
{
public:
bool operator()(const int value) const
{
return value>2;
}
};
template <class Arg1, class Arg2, class Result>
struct binary_function {
typedef Arg1 first_argument_type; // 参数类型别名
typedef Arg2 second_argument_type; // 参数类型别名
typedef Result result_type; // 返回值类型别名
};
举例:
//4.使用2元仿函数
class CopyClassUpNum : public binary_function<int, int, bool>
{
public:
bool operator()(const int srcValue, const int base) const
{
return srcValue > base;
}
};
//////算术类仿函数 + - * / %////////////////////////////////
//plus仿函数,生成一个对象,里面仅仅有一个函数重载的方法。
template <class T>
struct plus : public binary_function<T, T, T> {
T operator()(const T& x, const T& y) const { return x + y; }
};
//minus仿函数
template <class T>
struct minus : public binary_function<T, T, T> {
T operator()(const T& x, const T& y) const { return x - y; }
};
template <class T>
struct multiplies : public binary_function<T, T, T> {
T operator()(const T& x, const T& y) const { return x * y; }
};
template <class T>
struct divides : public binary_function<T, T, T> {
T operator()(const T& x, const T& y) const { return x / y; }
};
template <class T>
struct modulus : public binary_function<T, T, T> {
T operator()(const T& x, const T& y) const { return x % y; }
};
//取负值
template <class T>
struct negate : public unary_function<T, T> {
T operator()(const T& x) const { return -x; }
};
#include // std::cout
#include // std::plus
#include // std::transform
using namespace std;
int main(void)
{
cout << minus<int>()(10,5) << endl;//5
cout << multiplies<int>()(10,5) << endl;//50
cout << divides<int>()(10,5) << endl;//2
cout << modulus<int>()(10,5) << endl;//0
cout << negate<int>()(10) << endl;//-10
return 0;
}
//关系运算符仿函数////////////////////////////////////////////
// x==y 仿函数
template <class T>
struct equal_to : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const { return x == y; }
};
// x!=y 仿函数
template <class T>
struct not_equal_to : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const { return x != y; }
};
// x>y 仿函数
template <class T>
struct greater : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const { return x > y; }
};
// x
template <class T>
struct less : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const { return x < y; }
};
// x>=y 仿函数
template <class T>
struct greater_equal : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const { return x >= y; }
};
// x<=y 仿函数
template <class T>
struct less_equal : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const { return x <= y; }
};
举例
// sort algorithm example
#include // std::cout
#include // std::sort
#include // std::vector
#include // std::
bool myfunction (int i,int j) { return (i < j); }
int main () {
int myints[] = {32,71,12,45,26,80,53,33};
std::vector<int> myvector (myints, myints+8); // 32 71 12 45 26 80 53 33
// using default comparison (operator <):
std::sort (myvector.begin(), myvector.begin()+4); //(12 32 45 71)26 80 53 33
// using function as comp
std::sort (myvector.begin()+4, myvector.end(), myfunction); // 12 32 45 71(26 33 53 80)
// using object as comp
std::sort (myvector.begin(), myvector.end(), std::less<int>()); //(12 26 32 33 45 53 71 80)
// print out content:
std::cout << "myvector contains:";
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
template <class T>
struct logical_and : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const { return x && y; }
};
template <class T>
struct logical_or : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const { return x || y; }
};
template <class T>
struct logical_not : public unary_function<T, bool> {
bool operator()(const T& x) const { return !x; }
};
bind1st, bind2nd, not1,compose1,compose2
等等,这些适配器都是仿函数,同时以要适配的仿函数作为member object
。binary_function()
或者unary_function()
,只有继承自这两种父类,你声明的仿函数才可以融入STL
bind2nd()
.它的作用是绑定仿函数的第二参数
// binder2nd example
#include
#include
#include
using namespace std;
int main () {
int numbers[] = {10,-20,-30,40,-50};
int cx;
int cx1;
binder2nd< less<int> > IsNegative (less<int>(),0);//将less重新包装产生新的对象binder2nd
cx = count_if (numbers,numbers+5 , IsNegative);//二者用法一样
cx1 = count_if (numbers,numbers+5,bind2nd(less<int>() , 0));
cout << "There are " << cx <<" "<< cx1 << " negative elements.\n";//输出3,小于0的value有3个
return 0;
}
bind2nd()函数的作用: 它将0 这个变量绑定在less()函数的第二参数上,less函数返回第一参数是否小于第二参数,那么绑定后的less()函数就应该返回 传入的参数是否小于0.
具体源码分析过程如下:
1、less()的源码:
template <class T> struct less {
bool operator() (const T& x, const T& y) const {return x<y;}
typedef T first_argument_type;
typedef T second_argument_type;
typedef bool result_type;
};
他也是一个仿函数,但是却发现它没有继承自binary_function
2、bind2nd()的源代码:
template<typename _Operation, typename _Tp>
inline binder2nd<_Operation>//注意这里的返回类型是binder2nd
bind2nd(const _Operation& __fn, const _Tp& __x)
{
typedef typename _Operation::second_argument_type _Arg2_type;//这有一个typedef 它提取出operation的第二参数,同时可以检测第二参数类型
return binder2nd<_Operation>(__fn, _Arg2_type(__x));
}
3、binder2nd()的源码:
template<typename _Operation>
class binder2nd
: public unary_function<typename _Operation::first_argument_type,
typename _Operation::result_type>
{
protected:
_Operation op;//取出传进的仿函数
typename _Operation::second_argument_type value;//取出第二参数,同时可检测第二参数类型
public:
binder2nd(const _Operation& __x,
const typename _Operation::second_argument_type& __y)
: op(__x), value(__y) { }//构造函数(在bind2nd()函数中调用),初始化自身成员变量 op,value
typename _Operation::result_type
operator()(const typename _Operation::first_argument_type& __x) const
{ return op(__x, value); }//重载operator() 在函数count_if()中被调用
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 109. Missing binders for non-const sequence elements
typename _Operation::result_type
operator()(typename _Operation::first_argument_type& __x) const
{ return op(__x, value); }//非const
} _GLIBCXX_DEPRECATED;
4、count_if()的源码:
template <class Inputerator, class Outputerator, class Predicate>
typename iterator_traits<Inputerator>::difference_type;
count_if(Inputerator first, Inputerator last, Predicate pred)
{
typename iterator_traits<Inputerator>::difference_type;
for( ; first != last; ++first)
if(pred(*first)) //这个地方会调用函数pred(*first), 重上面我们可以看到 pred绑定的函数是binder2nd()中的 operator()函数,那么此时的pred就应该是less函数
++n;
return n;
}
#includ
#include
#include
using namespace std;
bool Cmp(int a,int b)
{
return a>b;
}
class Cmp2
{
public:
bool operator()(int a,int b)
{
return a>b;
}
};
class printElem
{
public:
void operator () (int elem)
{
cout<<elem<<" ";
}
};
int main(void)
{
vector<int> ver{0,9,4,3,8};
//使用函数指针
sort(ver.begin(),ver.end(),*Cmp);
for_each(ver.begin(),ver.end(),printElem ());
cout<<endl;//输出9 8 4 3 0
vector<int> ver2{1,3,8,9,4};
//使用仿函数
sort(ver2.begin(),ver2.end(),Cmp2());
for_each(ver2.begin(),ver2.end(),printElem ());
cout<<endl;//输出9 8 4 3 1
vector<int> ver3{5,8,3,7,9};
//使用Lambda表达式
sort(ver3.begin(),ver3.end(),[](int a,int b){return a>b;});
for_each(ver3.begin(),ver3.end(),printElem ());
cout<<endl;//输出9 8 7 5 3
return 0;
}
1、https://blog.csdn.net/u010710458/article/details/79734558
2、https://www.cnblogs.com/jiu0821/p/6554169.html
3、https://blog.csdn.net/u013427969/article/details/78587276
4、https://www.cnblogs.com/LearningTheLoad/p/7594646.html
5、<
6、https://blog.csdn.net/qq_46239972/article/details/106526106