您的位置:首页 > 其它

part5:仿函数,仿函数类(一)

2016-07-17 20:33 337 查看
Rule38:把仿函数类设计为用于值传递

Rule39:用纯函数做判断式

一个行为良好的operator()当然是const,但不只如此。它也得是一个纯函数。不要修改内部成员对象的值,否则会出现未定义的情况。要记住纯函数没有状态,良好的operator也没有。判断式和判断式对象的operator()都是没有状态的。

Rule40:使用仿函数类可适配

关于仿函数,仿函数类我们主要讲解这一部分。我们看,如下的例子:

我们有如下代码,找到第一个有趣的Widget。

class Widget{
//测试用不需要内容
public:
int id;
Widget(int id)
{
this->id = id;
}
};
bool isInteresting(const Widget* pw)
{
if (pw->id == 2)
{
return true;
}
return false;
}
list<Widget*> lwptrs;
lwptrs.push_back(new Widget(1));
lwptrs.push_back(new Widget(2));
list<Widget*>::iterator it = find_if(lwptrs.begin(),lwptrs.end(),isInteresting);


我们通过这种方法是可以的,这是基于仿函数,其实参数isInteresting这是一个函数指针。

现在如果我想要找第一个指向不有趣的Widget的指针,显而易见的方法却编译失败:

list<Widget*>::iterator it = find_if(lwptrs.begin(),lwptrs.end(),not1(isInteresting));


我们需要对isInteresting应用ptr_fun在应用not1之前。

list<Widget*>::iterator it = find_if(lwptrs.begin(),lwptrs.end(),not1(ptr_fun(isInteresting)));


ptr_fun做的唯一的事是使一些typedef有效。not1需要这些typedef,这就是为什么可以把not1应用于ptr_fun,但不能直接对isInteresting应用not1。因为是第几的函数指针,isInteresting缺乏not1需要的typedef。

四个标准函数适配器(not1,not2,bind1st,bind2nd)都需要存在某些typedef。我们应该使调用简单,我们不需要知道任何关于那些typedef的事情。operator()带一个实参的仿函数类,要继承的结构是std::unary_function。operator()带有两个实参的仿函数类,要继承的结构是std::binary_function。

template<typename T>
class MeetsThreshold: public std::unary_function<Widget, bool>{
private:
const T threshold;

public:
MeetsThreshold(const T& threshold);
bool operator()(const Widget&) const;
...
};

struct WidgetNameCompare:
public std::binary_function<Widget, Widget, bool>{
bool operator()(const Widget& lhs, const Widget& rhs) const;
};


unary_function一元,binary_function二元,模板化的最后一个参数与operator()的返回值相同

MeetsThreshold是一个类,而WidgetNameCompare是一个结构。因为一元MeetsThreshold可以有内部状态值,而类是封装那些信息的合理办法。WidgetNameCompare没有状态,因此不需要任何private东西。

Rule41:了解使用ptr_fun,memfun。

我们知道如下调用是合理的。

void test(Widget &w);
vector<Widget> vw;
for_each(vw.begin(),vw.end(),test);


对vw的每个元素调用test方法。

如果test是一个Widget的成员函数,而不是一个非成员函数,像这样。

class Widget{
public:
void test();
};


我们期待这么调用:

for_each(vw.begin(),vw.end(),&Widget::test);


但是,STL期待的调用形式就是使用非成员函数的语法形式调用。

所以mem_fun产生了,他们让成员函数可以那么调用。

template<typename R, typename C>        // 用于不带参数的non-const成员函数
mem_fun_t<R,C>              // 的mem_fun声明。
mem_fun(R(C::*pmf)());          // C是类,R是被指向
// 的成员函数的返回类型


mem_fun带有一个到成员函数的指针pmf,并返回一个mem_fun_t类型的对象。这是一个仿函数类,容纳成员函数指针并提供一个operator(),它调用指向在传给operator()的对象上的成员函数。

正确使用方法如下:

for_each(lpw.begin(), lpw.end(),
mem_fun(&Widget::test));
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: