C 的动作类?(相当于C#)

Action class in C++? (equivalent to C#)

本文关键字:相当于 动作类      更新时间:2023-10-16

在我的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 ::函数,但是为了删除对象破坏的方法,我必须将绘制方法存储在呼叫者拥有的指针中,然后将其包装到lambda中并将其传递。和耗时。

是否有任何方法可以获取与C#示例中显示的代码类似的代码?

您可以使用std::function代替Action

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

其他一些想法不使用std :: function,它使用std :: set,您为要执行的每个操作创建一个类。这个想法是,操作类是在CPP文件中定义的(不在标题文件中,除非共享)使用它们,它们完全隐藏了。

首先定义 Action 类,它具有纯虚拟执行,优先级级别和指向某些所有者的指针。这个想法是不要创建其他类,元组,而是使用 Action 类存储这些值:

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