C++ 在向量上迭代和调用函数

C++ 在向量上迭代和调用函数,c++,stl,foreach,iteration,C++,Stl,Foreach,Iteration,我有一个类,它有另一个类对象的向量作为成员。在此类的许多函数中,我必须对向量中的所有对象执行相同的操作: class Small { public: void foo(); void bar(int x); // and many more functions }; class Big { public: void foo() { for (size_t i = 0; i < VectorOfSmalls.size();

我有一个类,它有另一个类对象的向量作为成员。在此类的许多函数中,我必须对向量中的所有对象执行相同的操作:

class Small
{
  public:
    void foo(); 
    void bar(int x);
    // and many more functions
};

class Big
{
  public:
    void foo()
    {
        for (size_t i = 0; i <  VectorOfSmalls.size(); i++)
            VectorOfSmalls[i]->foo();
    }
    void bar(int x)
    {
        for (size_t i = 0; i <  VectorOfSmalls.size(); i++)
            VectorOfSmalls[i]->bar(x);
    }
    // and many more functions
  private:
    vector<Small*> VectorOfSmalls;
};
小类
{
公众:
void foo();
空心条(int x);
//还有更多的功能
};
班级大
{
公众:
void foo()
{
对于(size_t i=0;ifoo();
}
空栏(整数x)
{
对于(size_t i=0;ibar(x);
}
//还有更多的功能
私人:
向量小向量;
};
我想简化代码,并找到一种方法,避免在每个函数中重复向量

我考虑过创建一个函数,该函数接收指向函数的指针,并对向量的每个成员调用定点函数。但是我不确定在C++中使用指针的函数是个好主意。 我也一直在考虑函子和,但这会迫使我为每个函数创建一个类,这听起来有点过分了

另一种可能的解决方案是创建一个函数,该函数接收字符串,并根据该字符串调用命令:

void Big::call_command(const string & command)
{
    for (size_t i = 0; i <  VectorOfSmalls.size(); i++)
    {
       if (command == "foo")
           VectorOfSmalls[i]->foo();
       else if (command == "bar")
           VectorOfSmalls[i]->bar();
    }
}
void Big::foo()
{
    call_command("foo");
}
void Big::call_命令(常量字符串和命令)
{
对于(size_t i=0;ifoo();
else if(命令==“bar”)
向量小[i]->bar();
}
}
void Big::foo()
{
调用_命令(“foo”);
}
但它可能工作缓慢(不需要创建字符串而不仅仅是函数调用),如果函数具有不同的签名,也会产生问题

那你有什么建议?我应该让一切都保持现在的样子吗


编辑:我只能使用STL,不能使用boost(旧编译器)。

如果您使用的是std库,您应该看看


你提到使用C++中的函数指针可能不是一个好主意,但是让你的担心是速度——你必须看看这是否是一个性能瓶颈区域,在担心之前。

< P>你可以重写for循环使用迭代器和更多的STL,像这样:

void foo() {
    std::for_each(VectorOfSmalls.begin(), VectorOfSmalls.end(), std::mem_fun(&Small::foo));
}

void bar() {
    std::for_each(VectorOfSmalls.begin(), VectorOfSmalls.end(), std::mem_fun(&Small::bar));
}
除此之外,您还可以使用一些宏来避免多次重新键入,但我不太喜欢这样。就我个人而言,我喜欢多个函数,而不是一个接受命令字符串的函数。因为它能让你更灵活地做出决定

如果你使用一个函数,用一个参数来决定该做什么,我会使用一个枚举和一个这样的开关,它会比字符串和级联If更有效。此外,在您的示例中,您可以使用if来决定在循环中执行哪些操作。在循环外部进行检查更有效,并且拥有循环的冗余副本,因为每次调用只需要确定一次“哪个命令”。(注意:如果在编译时知道该命令,您可以将其设置为模板参数,听起来似乎是这样)

另外,正如您所提到的,替换&Small::whatever,what,成员函数指针并将其作为参数传递是非常简单的。你甚至可以把它做成一个模板

class Big {
public:
    template<void (Small::*fn)()>
    void doit() {
        std::for_each(VectorOfSmalls.begin(), VectorOfSmalls.end(), std::mem_fun(fn));
    }
};
大类{
公众:
模板
void doit(){
std::for_each(VectorOfSmalls.begin()、VectorOfSmalls.end()、std::mem_fun(fn));
}
};
然后你可以做:

Big b;
b.doit<&Small::foo>();
b.doit<&Small::bar>();
大b;
b、 doit();
b、 doit();
这个方法和常规参数方法的优点是,如果您更改了小的方法以拥有更多的例程,那么大的方法就不需要更改!我认为这是首选的方法

如果希望能够处理单个参数,还需要添加BindSecond,下面是一个完整的示例:

#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>

class Small {
public:
    void foo() { std::cout << "foo" << std::endl; }
    void bar(int x) { std::cout << "bar" << std::endl; }
};


class Big {
public:
    template<void (Small::*fn)()>
    void doit() {
        std::for_each(VectorOfSmalls.begin(), VectorOfSmalls.end(), std::mem_fun(fn));
    }

    template<class T, void (Small::*fn)(T)>
    void doit(T x) {
        std::for_each(VectorOfSmalls.begin(), VectorOfSmalls.end(), std::bind2nd(std::mem_fun(fn), x));
    }
public:
    std::vector<Small *> VectorOfSmalls;
};

int main() {
    Big b;
    b.VectorOfSmalls.push_back(new Small);
    b.VectorOfSmalls.push_back(new Small);

    b.doit<&Small::foo>();
    b.doit<int, &Small::bar>(5);
}
#包括
#包括
#包括
#包括
小班{
公众:
void foo(){std::cout尝试并:

void Big::call_命令(const boost::function&f)
{
对于(size_t i=0;i
谢谢Evan。但是std::mem\u fn是boost的一部分,而不是STL。在我的例子中,也许每个函数都有另一种使用方法?那么具有不同签名的函数呢?哦,打字:mem\u fn是boost的一部分,但是std::mem\u fun是STL的一部分。对于具有不同签名的函数,您可能会使用一些模板函数来覆盖它们所有的可能性。在枚举示例中,使用模板void foo(){switch(cmd){case A:/*bla*/case B:/*bla*/;}来避免任何运行时惩罚。这是一个很好的解决方案(尽管您应该使用std::for_)。但不幸的是,他说boost是一个可行的选项。为什么要投反对票?我在编辑之前回答他补充说他不能使用boost。
#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>

class Small {
public:
    void foo() { std::cout << "foo" << std::endl; }
    void bar(int x) { std::cout << "bar" << std::endl; }
};


class Big {
public:
    template<void (Small::*fn)()>
    void doit() {
        std::for_each(VectorOfSmalls.begin(), VectorOfSmalls.end(), std::mem_fun(fn));
    }

    template<class T, void (Small::*fn)(T)>
    void doit(T x) {
        std::for_each(VectorOfSmalls.begin(), VectorOfSmalls.end(), std::bind2nd(std::mem_fun(fn), x));
    }
public:
    std::vector<Small *> VectorOfSmalls;
};

int main() {
    Big b;
    b.VectorOfSmalls.push_back(new Small);
    b.VectorOfSmalls.push_back(new Small);

    b.doit<&Small::foo>();
    b.doit<int, &Small::bar>(5);
}
void Big::call_command(const boost::function<void (Small*)>& f)
{
    for (size_t i = 0; i <  VectorOfSmalls.size(); i++)
    {
        f(VectorOfSmalls[i]);
    }
}

int main()
{
    Big b;
    b.call_command(boost::bind(&Small::foo, _1));
    b.call_command(boost::bind(&Small::bar, _1, 5));
}