本文最初发表于SpriteLW的博客http://blog.csdn.net/SpriteLW,欢迎转载,但请务必保留原文完整,并保留本声明。
首先要知道什么是函数子,什么是函数子类,与其和函数的区别。简单地说,函数子是一个对象,而函数子类是该对象的类,并且该类要实现operator();函数是在类之外的函数,例如:
struct
MaxWeight:
public
binary_function
<
Widget,Widget,
bool
>
{
bool operator ()( const Widget & lhs, const Widget & rhs)
{
return lhs.m_weigth > rhs.m_weigth ;
}
};
int Print( const Widget & w)
{
printf( " %d " ,w.m_weigth);
return 0 ;
}
{
bool operator ()( const Widget & lhs, const Widget & rhs)
{
return lhs.m_weigth > rhs.m_weigth ;
}
};
int Print( const Widget & w)
{
printf( " %d " ,w.m_weigth);
return 0 ;
}
类MaxWeight为函数子类,Print为函数。用class或struct因个人风格而定。
设类Widget有属性weight,现要对它进行显示。有以下几种方法
#include
<
vector
>
#include < iostream >
#include < functional >
#include < algorithm >
using namespace std;
class Widget
{
public :
int m_weight;
// 成员函数
int printWithClassMemberFunction()
{
cout << m_weight << " " ;
return 0 ;
}
// 内部函数子类
struct PrintWithInnerClass: public unary_function < Widget, void >
{
void operator ()( const Widget & w)
{
cout << w.m_weight << " " ;
}
};
};
// 外部函数子类
struct PrintWithOuterClass: public unary_function < Widget, void >
{
void operator ()( const Widget & w)
{
cout << w.m_weight << " " ;
}
};
// 外部函数
int PrintWithOuterFunction( const Widget & w)
{
cout << w.m_weight << " " ;
return 0 ;
}
int main( int argc, char * argv[])
{
const int MaxCount = 20 ;
// 容器元素为非指针
vector < Widget > vDataWithNonPoint;
for ( int i = 0 ; i < MaxCount; i ++ )
{
Widget w;w.m_weight = rand() % MaxCount;
vDataWithNonPoint.push_back(w);
}
cout << " PrintWithOuterFunction: " << endl;
for_each(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),PrintWithOuterFunction);
cout << endl << " ptr_fun(PrintWithOuterFunction): " << endl;
for_each(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),ptr_fun(PrintWithOuterFunction));
cout << endl << " mem_fun_ref(Widget::printWithClassMemberFunction) " << endl;
for_each(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),mem_fun_ref(Widget::printWithClassMemberFunction));
cout << endl << " Widget::PrintWithInnerClass() " << endl;
for_each(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),Widget::PrintWithInnerClass());
cout << endl << " PrintWithOuterClass() " << endl;
for_each(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),PrintWithOuterClass());
cout << endl;
system( " PAUSE " );
return 0 ;
}
#include < iostream >
#include < functional >
#include < algorithm >
using namespace std;
class Widget
{
public :
int m_weight;
// 成员函数
int printWithClassMemberFunction()
{
cout << m_weight << " " ;
return 0 ;
}
// 内部函数子类
struct PrintWithInnerClass: public unary_function < Widget, void >
{
void operator ()( const Widget & w)
{
cout << w.m_weight << " " ;
}
};
};
// 外部函数子类
struct PrintWithOuterClass: public unary_function < Widget, void >
{
void operator ()( const Widget & w)
{
cout << w.m_weight << " " ;
}
};
// 外部函数
int PrintWithOuterFunction( const Widget & w)
{
cout << w.m_weight << " " ;
return 0 ;
}
int main( int argc, char * argv[])
{
const int MaxCount = 20 ;
// 容器元素为非指针
vector < Widget > vDataWithNonPoint;
for ( int i = 0 ; i < MaxCount; i ++ )
{
Widget w;w.m_weight = rand() % MaxCount;
vDataWithNonPoint.push_back(w);
}
cout << " PrintWithOuterFunction: " << endl;
for_each(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),PrintWithOuterFunction);
cout << endl << " ptr_fun(PrintWithOuterFunction): " << endl;
for_each(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),ptr_fun(PrintWithOuterFunction));
cout << endl << " mem_fun_ref(Widget::printWithClassMemberFunction) " << endl;
for_each(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),mem_fun_ref(Widget::printWithClassMemberFunction));
cout << endl << " Widget::PrintWithInnerClass() " << endl;
for_each(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),Widget::PrintWithInnerClass());
cout << endl << " PrintWithOuterClass() " << endl;
for_each(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),PrintWithOuterClass());
cout << endl;
system( " PAUSE " );
return 0 ;
}
输出如下:
PrintWithOuterFunction:
1 7 14 0 9 4 18 18 2 4 5 5 1 7 1 11 15 2 7 16
ptr_fun(PrintWithOuterFunction):
1 7 14 0 9 4 18 18 2 4 5 5 1 7 1 11 15 2 7 16
mem_fun_ref(Widget::printWithClassMemberFunction)
1 7 14 0 9 4 18 18 2 4 5 5 1 7 1 11 15 2 7 16
Widget::PrintWithInnerClass()
1 7 14 0 9 4 18 18 2 4 5 5 1 7 1 11 15 2 7 16
PrintWithOuterClass()
1 7 14 0 9 4 18 18 2 4 5 5 1 7 1 11 15 2 7 16
有以下几个问题要注意:
1、 对PrintWithOuterFunction 和 ptr_fun(PrintWithOuterFunction) 操作,似乎ptr_fun是多余的。准确地说是在特定情况下ptr_fun可有可无,当要用not2,bind1st时就必须加上ptr_fun,因为ptr_fun的作用是把OuterFunction转unary_function<Widget,void>类似的类型,其它的还有binary_function,那正是not2,bind1st等函数所需要的
2、 为什么printWithClassMemberFunction返回int?如果不加ptr_fun则返回void也可以,但如果加了ptr_fun则必需要返回一个类型,不知是不是vc的原因,void似乎不认void为类型
3、 对函数子类的用法(外部类或内部类),类型名后一定要加()。似乎是调用operator(),其实不是,它是创建了一个匿名对象,俗称“函数子”,所以for_each里调用的都是一个函数子。
4、 为什么我要注明“容器元素为非指针”?回答这个问题,我要对上述每个函数作一个讲解。
4.1 for_each(。。。。,PrintWithOuterFunction):
for_each每次迭代都传给
函数PrintWithOuterFunction一个Widget,这正是PrintWithOuterFunction形参的类型
4.2 for_each(。。。。, mem_fun_ref(Widget::printWithClassMemberFunction)):
for_each每次迭代都对容器中的一个元素 I 调用 I. printWithClassMemberFunction()。注意,因为容器元素类型为“非指针”,所以调用”.”方法,当容器元素类型为“指针”时,则要将mem_fun_ref改为mem_fun,在内部,它对每个容器元素I,调用I->printWithClassMemberFunction()。(如果printWithClassMemberFunction有参数呢?那就要调用bind方法了)
4.3 Widget::PrintWithInnerClass()和PrintWithOuterClass():
For_each会对函数子进行操作,调用void operator()(const Widget &w),那么for_each怎么会知道要传一个Widget参数和返回void呢?那是因为函数子类继承自unary_function<Widget,void>的原因,其中<>中,第一个为参数类型,第二个为返回类型。
到目前为止,我们的“函数子”都是一个参数或无参数的,现在要看有两个参数的情况,那就是要为Widget排序:
#include
<
vector
>
#include < iostream >
#include < functional >
#include < algorithm >
using namespace std;
class Widget
{
public :
int m_weight;
// 成员函数
bool operator < ( const Widget & rhs)
{
return this -> m_weight < rhs.m_weight;
}
// 成员函数
bool LessWeightWithMemberFunction( const Widget & rhs)
{
return this -> m_weight < rhs.m_weight;
}
// 内部类
struct LessWeightWithInnerClass: public binary_function < Widget,Widget, bool >
{
bool operator ()( const Widget & lhs, const Widget & rhs) const
{
return lhs.m_weight < rhs.m_weight;
}
};
};
// 调用less<Widget>时内部调用operator<
bool operator < ( const Widget & lhs, const Widget & rhs)
{
return lhs.m_weight < rhs.m_weight;
}
bool lessWeightWithOutFunction( const Widget & lhs, const Widget & rhs)
{
return lhs.m_weight < rhs.m_weight;
}
// 外部函数子类
struct LessWeightWithOuterClass: public binary_function < Widget,Widget, bool >
{
bool operator ()( const Widget & lhs, const Widget & rhs) const
{
return lhs.m_weight < rhs.m_weight;
}
};
// 外部函数子类
struct PrintWithOuterClass: public unary_function < Widget, void >
{
void operator ()( const Widget & w)
{
cout << w.m_weight << " " ;
}
};
int main( int argc, char * argv[])
{
const int MaxCount = 20 ;
// 容器元素为非指针
vector < Widget > vDataWithNonPoint;
for ( int i = 0 ; i < MaxCount; i ++ )
{
Widget w;w.m_weight = rand() % MaxCount;
vDataWithNonPoint.push_back(w);
}
// 默认调用类内部的operator<
sort(vDataWithNonPoint.begin(),vDataWithNonPoint.end());
// 调用外部的bool operator<(const Widget& lhs,const Widget& rhs)
sort(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),less < Widget > ());
// 调用类成员函数
sort(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),mem_fun1_ref(Widget::LessWeightWithMemberFunction ));
// 调用外部函数
sort(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),lessWeightWithOutFunction);
// 调用内部函数子类
sort(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),Widget::LessWeightWithInnerClass());
// 调用外部函数子类
sort(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),LessWeightWithOuterClass());
for_each(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),PrintWithOuterClass());
cout << endl;
system( " PAUSE " );
return 0 ;
}
#include < iostream >
#include < functional >
#include < algorithm >
using namespace std;
class Widget
{
public :
int m_weight;
// 成员函数
bool operator < ( const Widget & rhs)
{
return this -> m_weight < rhs.m_weight;
}
// 成员函数
bool LessWeightWithMemberFunction( const Widget & rhs)
{
return this -> m_weight < rhs.m_weight;
}
// 内部类
struct LessWeightWithInnerClass: public binary_function < Widget,Widget, bool >
{
bool operator ()( const Widget & lhs, const Widget & rhs) const
{
return lhs.m_weight < rhs.m_weight;
}
};
};
// 调用less<Widget>时内部调用operator<
bool operator < ( const Widget & lhs, const Widget & rhs)
{
return lhs.m_weight < rhs.m_weight;
}
bool lessWeightWithOutFunction( const Widget & lhs, const Widget & rhs)
{
return lhs.m_weight < rhs.m_weight;
}
// 外部函数子类
struct LessWeightWithOuterClass: public binary_function < Widget,Widget, bool >
{
bool operator ()( const Widget & lhs, const Widget & rhs) const
{
return lhs.m_weight < rhs.m_weight;
}
};
// 外部函数子类
struct PrintWithOuterClass: public unary_function < Widget, void >
{
void operator ()( const Widget & w)
{
cout << w.m_weight << " " ;
}
};
int main( int argc, char * argv[])
{
const int MaxCount = 20 ;
// 容器元素为非指针
vector < Widget > vDataWithNonPoint;
for ( int i = 0 ; i < MaxCount; i ++ )
{
Widget w;w.m_weight = rand() % MaxCount;
vDataWithNonPoint.push_back(w);
}
// 默认调用类内部的operator<
sort(vDataWithNonPoint.begin(),vDataWithNonPoint.end());
// 调用外部的bool operator<(const Widget& lhs,const Widget& rhs)
sort(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),less < Widget > ());
// 调用类成员函数
sort(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),mem_fun1_ref(Widget::LessWeightWithMemberFunction ));
// 调用外部函数
sort(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),lessWeightWithOutFunction);
// 调用内部函数子类
sort(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),Widget::LessWeightWithInnerClass());
// 调用外部函数子类
sort(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),LessWeightWithOuterClass());
for_each(vDataWithNonPoint.begin(),vDataWithNonPoint.end(),PrintWithOuterClass());
cout << endl;
system( " PAUSE " );
return 0 ;
}
有以下几个问题要注意:
1、函数子类继承自binary_function<Widget,Widget,bool>,它表示要输入两个参数,并返回bool。
2、成员函数的“包装”由mem_fun_ref改为mem_fun1_ref