需要某种方法将函数存储在列表中,然后调用它们

时间:2011-09-23 03:47:23

标签: c++ list function stl

这个列表必须包含函数,它们可能来自不同的命名空间甚至是实例类的方法 然后将迭代此列表并调用所有函数和方法。如果他们也可以包含参数那就太好了。

我正在考虑使用std :: vector,但我怀疑这个猜测远非正确。

你推荐我什么方法?欢迎大家帮忙。

3 个答案:

答案 0 :(得分:4)

如果你的编译器已经支持它,你可以使用std :: function和std :: bind。

#include <functional>
#include <vector>

void x(int) {}
void y() {}
class Z {
public:
    void z() {}
};

int main(int argc, char *argv[])
{
    typedef std::function<void ()> VoidFunc;
    typedef std::vector<VoidFunc> FuncVector;
    FuncVector functions;

    functions.push_back(std::bind(&x, 1));
    functions.push_back(&y);
    Z z1;
    functions.push_back(std::bind(&Z::z, z1));

    for(FuncVector::iterator i = functions.begin(); i != functions.end(); i++) {
        (*i)();
    }

    return 0;
}

答案 1 :(得分:2)

如果您不想使用现有的解决方案,例如boost :: function,则需要创建一个表示函数的基类,然后创建包含各种函数源的派生类。例如:

#include <iostream>
#include <list>
using std::cout;
using std::list;

struct Function {
  virtual ~Function() { }
  virtual void operator()() = 0;
};

struct PlainFunction : Function {
  PlainFunction(void (*function_ptr_arg)()) : function_ptr(function_ptr_arg) { }
  virtual void operator()() { (*function_ptr)(); }
  void (*function_ptr)();
};

template <typename T> 
struct MethodFunction : Function {
  MethodFunction(T &obj_arg,void (T::*method_ptr_arg)())
    : obj(obj_arg), method_ptr(method_ptr_arg)
  {
  }
  virtual void operator()() { (obj.*method_ptr)(); }
  T &obj;
  void (T::*method_ptr)();
};

void f()
{
  cout << "Called f()\n";
}

struct A {
  void f() { cout << "Called A::f()\n"; }
};

int main(int argc,char **argv)
{
  list<Function *> functions;
  functions.push_back(new PlainFunction(f));
  A a;
  functions.push_back(new MethodFunction<A>(a,&A::f));
  list<Function *>::iterator i = functions.begin();
  for (;i!=functions.end();++i) {
    (*(*i))();
  }
  while (!functions.empty()) {
    Function *last_ptr = functions.back();
    functions.pop_back();
    delete last_ptr;
  }
}

答案 2 :(得分:2)

让您的所有功能都实现Command Pattern.

您的列表变为

std::list<Command>

当您遍历列表时,您将调用每个列表项的Execute()方法。

例如,假设您有一个名为Commander的简单Command接口:

class Commander
{
public:
    virtual        ~Commander;

    virtual void    Execute();//= 0;
};

你想在列表中放置三个物品:灰狗,Gyrefalcon和女朋友。将每个包装在调用对象感兴趣的函数的Commander对象中。灰狗跑:

class RunGreyhound: public Commander
{
public:
    void            Execute()
                    {
                        mGreyhound->Run();
                    }
private:
    Greyhound*      mGreyhound;
};

Gyrefalcon苍蝇:

class RunGyrefalcon: public Commander
{
public:
    void            Execute()
                    {
                        mGyrefalcon->Fly( mGyrefalcon->Prey() );
                    }    
private:
    Gyrefalcon*      mGyrefalcon;
};

女朋友吵了一声:

class RunGirlfriend: public Commander
{
public:
    void            Execute()
                    {
                        mGirlfriend->Squawk( mGirlfriend->MyJunk(), mGirlfriend->Mytrun() );
                    }
private:
    Girlfriend*     mGirlfriend;
};

填充列表中的Commander对象。现在你可以迭代它们并调用每个元素的Execute()方法:

std::list<Commander> cmdlist;

RunGreyhound dog;
cmdlist.push_back( dog );

RunGyrefalcon bird;
cmdlist.push_back( bird );

RunGirlfriend gurl;
cmdlist.push_back( gurl );

for ( std::list<Commander>::iterator rit = cmdlist.begin(); rit != cmdlist.end(); ++rit )
{
    rit->Execute();
}