在一个类中放置for_each调用的函数的位置?

时间:2014-07-23 09:50:12

标签: c++ function-pointers

使用较新的C ++功能,您经常将函数作为参数提供,例如:

// File A.cpp    

void do_something(Foo* foo) { ... }

void A::process_foo(){
    for_each( foo_list.begin(), foo_list.end(), do_something );
}

但是当我使用类时,我应该在哪里实际放置函数do_something(...)?我不能把它变成私有成员,因为在将参数传递给for_each时我会松开this

所以我倾向于在我的实现文件A.cpp中定义一个普通函数do_something(...),就像上面的代码中给出的那样。由于只有A的实现才能看到这一点,所以我不会冒命名空间污染的风险。由于其他类中的类似函数也只能在其实现中可见,因此我也不会冒与其他类的类似函数发生名称冲突的风险。

这是正确的方法吗?

另一个想法是使用Lambda。我对Lambdas不是很熟悉,所以我不知道我是应该尽可能多地使用它们,还是只在绝对必要的时候使用它们......

2 个答案:

答案 0 :(得分:1)

std::for_each的第三个参数需要是具有一个参数的函数或函数对象,例如可以使用for_each的前两个参数定义的范围元素调用它。然后您有以下选项(假设foo_list存储Foo*):

使用常规功能

void do_someting(Foo*){...}
for_each(..., do_something);

您可以将功能放在任何合适的位置。如果这是供本地使用,则匿名命名空间是最佳选择。但它可能是例如在一个单独的编译单元中定义。

使用静态方法

static void do_something(Foo*){...}
for_each(..., &Foo::do_something);

请注意,它不一定是Foo的静态方法。

使用lambda

for_each(...,[](Foo* f){...});

使用Foo类的方法(甚至私有)和 std::bind

void method(){...}
for_each(..., std::bind(&Foo::method, _1));

还有其他选择,但这些选项最常见。

答案 1 :(得分:1)

C ++ 11解决方案

如果您可以使用C ++ 11,则更喜欢基于范围而不是std::for_each,并且只需编写代码就行。像这样:

for (const auto& value : foo_list)
{ 
  // do something with the value
}

它不那么冗长,也更方便。它逐个迭代所有元素,就像std::for_each算法一样。您可以通过const auto&或简单地auto(无需参考)明确指定您不想修改元素。

<强>偏-C ++ 11

如果您的编译器不支持基于范围的fors,但支持lambdas(如Visual Studio 2010),只需将函数放入lambda:

for_each( foo_list.begin(), foo_list.end(), 
  [] (const FooList::value_type& value) { /* do something with the value */; });

<强> C ++ 98

如果您不能使用上述C ++ 11功能,那么大多数STL算法看起来都很可怜。无论您将do_something函数置于何处,它都将与调用代码分离,这很难阅读。在这种情况下,首选基于简单迭代器:

for (FooList::iterator pValue = foo_list.begin(); pValue != foo_list.end(); ++pValue) 
{ 
  // do something with the pValue
}

PS 我更喜欢后一种形式,即使对于&#34; Partial-C ++ 11&#34; case,当你不能使用基于范围的fors时,可以用简单的FooList::iterator替换auto。当你不得不写一些更复杂的东西时,这是非常有用的,比如std::list<std::string>::const_iterator。我认为以下内容优于std::for_each lambda:

for (auto pValue = foo_list.begin(); pValue != foo_list.end(); ++pValue) 
{ 
  // do something with the pValue
}