总结下函数对象
函数对象可以认为是重载了()的对象。现在想想为什么不用函数指针来进行回调而使用函数指针。
①
for_each(books.begin() , books.end() , showreview);
它将指定的函数用于区间内的每个成员,如果把第三个参数声明为函数指针,那函数指针会指定参数的类型,但由于容器可以包容任意类型,所以预先无法知道应使用哪种参数类型,因此不能把它声明为函数指针。STL使用模板解决这个问题,for_each的原型看上去就像这样:
template<class InputIterator , class Function>
Function for_each(InputIterator first , InputIterator last , Function f);
其中f既可以接受函数指针,也可以接受函数对象的重载()的函数。
②另外函数对象比函数指针更为灵活
例如
bool GT6(const string &s)
{
return s.size() >= 6;
}
using namespace std;
int main()
{
string s1[10] = {"the","quick","yellow","fox","jumps","over","the","slow","red","turtle"};
vector<string> svec(s1,s1+10);
for(vector<string>::iterator iter = svec.begin();iter != svec.end();++iter)
cout<<*iter<<"\t";
vector<string>::size_type wc = count_if(svec.begin(),svec.end(),GT6);
cout<<wc<<endl;
return 0;
}
程序的关键是调用count_if函数来对容器做判断,这个函数接受一个谓词函数,这个谓词函数只有一个形参(类型与容器的中元素的类型相同),且返回值为bool。对于容器中的每个元素,利用谓词函数来判断容器的元素是否满足谓词,count_if的返回值为容器中满足谓词函数的个数。
但这个程序有一个小问题,就是由于count_if只能接受一个带一个形参,这个形参还必须是容器的元素的类型的谓词函数,所以“大于6”这个标准是写在代码中的,如果我们想修改判断标准:改成大于5,那么就必须动谓词函数程序了。这样用起来很不方便,我们希望能把这个标准变成一个参数传递进来,这时我们的函数对象就派上用场了。
class GT_cls
{
public:
GT_cls(size_t val = 0):bound(val){}
bool operator()(const string &s)
{
return s.size() >= bound;
}
private:
string::size_type bound;
};
我们为这个类提供了一个数据成员,并提供了一个带参数的构造函数!利用这个参数来控制比较的对象。于是我们就可以这样使用:
wc = count_if(svec.begin(),svec.end(),GT_cls(5));
可以发现,由于函数对象的使用,算法库中接受谓词的算法一下子就灵活了起来。
③虽然函数对象更为灵活,但是函数对象是一个类,类的建立、构造、析构 的开销都很大,而函数指针只是一个指针,对该指针寻址一次即可调用!
夹杂自己的理解并且参考了网上的资料,如有错误请指正!