【问题标题】:Need some way to store functions in a list, and then call them需要某种方法将函数存储在列表中,然后调用它们
【发布时间】:2025-12-24 17:30:11
【问题描述】:

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

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

你推荐我什么方法?欢迎所有帮助。

【问题讨论】:

  • 我们能否提供有关这些功能的更多细节? (即可能的返回类型和参数)另外,我认为您的意思是“迭代”而不是“递归”。
  • 几年前我说过要使用 boost:function,但现在我不知道...
  • @Colin:为什么不 boost::function?
  • @quasiverse 是的,你是对的,我在写长英文句子时有时会感到困惑。

标签: c++ list function stl


【解决方案1】:

如果您不想使用诸如 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】:

    让你的所有函数都实现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;
    };
    

    陀螺飞翔:

    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;
    };
    

    把指挥官物品塞进你的清单。现在您可以遍历它们并调用每个元素的 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();
    }
    

    【讨论】:

    • 我只是找不到任何关于此的文档。你能告诉我一个最小的代码让我理解吗?
    • 我用一个(非常)最小的例子扩展了我的答案。
    【解决方案3】:

    如果你的编译器已经支持,你可以使用 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;
    }
    

    【讨论】:

      最近更新 更多