2011-09-23 71 views
3

該列表必須包含函數,它們可能來自不同的命名空間,甚至是實例化類的方法。
這個列表將被迭代並調用所有的函數和方法。如果他們也可以包含參數將會很好。需要某種方式將函數存儲在列表中,然後調用它們

我在考慮使用std :: vector,但我懷疑在猜測中我是遠遠不夠的。

你推薦我什麼方法?歡迎所有幫助。

+0

我們可以有更多關於這些功能的細節嗎? (即可能的返回類型和參數)另外,我認爲你的意思是「迭代」而不是「遞歸」。 – quasiverse

+1

或者也許「遍歷」 – Colin

+0

幾年前我說過使用boost:函數,但是現在我不知道... – Colin

回答

2

有所有的功能實現Command Pattern.

您的列表變成

std::list<Command> 

當你遍歷列表,您可以調用每個列表的execute()方法項目。

例如,假設你有一個名爲指揮官一個簡單的命令界面:

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

的東西,在你的列表中的指揮官對象。現在你可以在它們之間迭代並調用每個元素的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(); 
} 
+0

我只是找不到任何關於此的文檔。你能告訴我一個最小的代碼讓我明白嗎? – 2011-09-23 20:55:00

+1

我用一個非常簡單的例子擴展了我的答案。 – Gnawme

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

你可以使用std ::函數和std ::綁定,如果你的編譯器已經支持它。

#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; 
} 
相關問題