2012-10-28 43 views
1

在我的C#遊戲引擎中,我曾經通過向經理對象添加/刪除操作來處理有序圖形,該對象按優先級對操作進行了排序,然後執行它們。C++中的動作類? (相當於C#)

這是非常簡單的例子:

class DrawManager 
{ 
    public List<Tuple<Action, int>> DrawActions = new List<Tuple<Action, int>>(); 
    void Draw() { foreach (var tuple in DrawActions) tuple.Item1(); } 
} 

class Example 
{ 
    DrawManager manager; 

    Example() 
    { 
     manager.DrawActions.Add(new Tuple<Action, int>(DrawBackground, 0)); 
     manager.DrawActions.Add(new Tuple<Action, int>(DrawForeground, 100)); 
    } 
    ~Example() 
    { 
     manager.DrawActions.Remove(manager.DrawActions.Find(x => x.Item1 == DrawBackground)); 
     manager.DrawActions.Remove(manager.DrawActions.Find(x => x.Item1 == DrawForeground)); 
    } 

    void DrawBackground() { /* draw something */ } 
    void DrawForeground() { /* draw something */ } 
} 

通過添加一些輔助方法,代碼變得非常優雅,易於在我的引擎使用。

我已經轉移到C++最近,我找不到任何簡單的方法來實現相同的結果。我試圖使用std :: function,但爲了刪除對象銷燬的方法,我不得不將draw方法存儲在調用方擁有的指針中,然後將其包裝到lambda中並傳入。不雅,耗時。

有什麼辦法可以獲得類似於C#示例中顯示的代碼嗎?

+0

這裏的東西類似,如果這有助於? http://forums.codeguru.com/showthread.php?489732.html – JohnLBevan

+0

Example類中的DrawManager對象是否被其他對象共享? –

+0

你能舉一個你用'std :: function'做的例子嗎?因爲我無法破譯你的描述。 :) – jalf

回答

4

可以代替使用std::functionAction

typedef std::function<void()> Action; 
std::vector<std::pair<Action, int> > DrawActions; 
void Draw() { 
    for_each(DrawActions.begin(), DrawActions.end(), [](std::pair<Action, int>& a) { 
     a.first(); 
    }); 
} 
+0

他正在那樣做。我認爲他的問題是他不知道如何從矢量中刪除函數,因爲他找不到它們,因爲'std :: function's是不可比較的。 –

0

一些其他的想法不使用std ::功能,它使用的std ::設置與您共創你要執行的每個動作類。這個想法是,動作類是在cpp文件中定義的(不是在頭文件中,除非它們是共享的),它們是完全隱藏的。

首先定義動作類,它具有一個純虛執行,優先級和一個指向一些所有者。我們的想法是不產生其他類,元組,但使用行動類來存儲這些值:

class Action 
{ 
public: 
    Action(const int priority, void * owner) : priority(priority), owner(owner) {} 
    virtual ~Action() {} 

    virtual void execute() = 0; 

    struct PrioritySorter 
    { 
     bool operator()(Action* a, Action* b) 
     { 
      return a->priority < b->priority; 
     } 
    }; 

    bool ownerIs(void * owner) const { return this->owner == owner; } 

private: 
    const int priority; 
    void * owner; 
}; 

然後創建了一些行動:

class DrawBackgroundAction : public Action 
{ 
public: 
    DrawBackgroundAction(const int priority, void * owner) : Action(priority, owner) {} 

    void execute() 
    { 
     cout << "drawing background" << endl; 
    } 
}; 

class DrawForegroundAction : public Action 
{ 
public: 
    DrawForegroundAction(const int priority, void * owner) : Action(priority, owner) {} 

    void execute() 
    { 
     cout << "drawing foreground!!!" << endl; 
    } 
}; 

class DrawSomethingElseAction : public Action 
{ 
public: 
    DrawSomethingElseAction(const int priority, void * owner) : Action(priority, owner) {} 

    void execute() 
    { 
     cout << "drawing something else" << endl; 
    } 
}; 

DrawManager需要存儲的護理按優先級排序的集合中的動作,如果想要刪除「擁有」的動作(某些其他類),則可以執行此操作。

class DrawManager 
{ 
public: 
    DrawManager() {} 
    ~DrawManager() 
    { 
     for (ActionList::iterator i = actions.begin(), e = actions.end(); i != e; i++) 
     { 
      delete *i; 
     } 
     actions.clear(); 
    } 

    void draw() 
    { 
     for (ActionList::iterator i = actions.begin(), e = actions.end(); i != e; i++) 
     { 
      (*i)->execute(); 
     } 
    } 

    void addAction(Action* action) 
    { 
     actions.insert(action); 
    } 

    void removeOwnedActions(void * owner) 
    { 
     for (ActionList::iterator i = actions.begin(), e = actions.end(); i != e; i++) 
     { 
      if ((*i)->ownerIs(owner)) 
      { 
       delete *i; 
       actions.erase(i); 
      } 
     } 
    } 

private: 
    typedef std::set<Action*,Action::PrioritySorter> ActionList; 
    ActionList actions; 
}; 

現在的例子類:

class Example 
{ 
public: 
    Example() 
    { 
     manager.addAction(new DrawForegroundAction(100,this)); 
     manager.addAction(new DrawBackgroundAction(0,this)); 
     manager.addAction(new DrawSomethingElseAction(50,this)); 
    } 

    void drawAll() 
    { 
     manager.draw(); 
    } 

    void removeTheActionsIfYouWant() 
    { 
     manager.removeOwnedActions(this); 
    } 

private: 
    DrawManager manager; 
}; 

而且測試:

int main() 
{ 
    Example ex; 

    cout << "Drawing all" << endl; 

    ex.drawAll(); 

    ex.removeTheActionsIfYouWant(); 

    cout << "Drawing again" << endl; 

    ex.drawAll(); 

    return 0; 
}