如何实现简单的事件队列?

时间:2014-10-03 08:21:44

标签: c++ events

所以,我先做了一个合理数量的谷歌搜索,但所有的解决方案似乎都过于复杂。所以,我想我会在这里问这个任务是否真的需要我遇到的那种方法...

所以,说我有一个Event课程。我希望它有一个time变量和一个functionToExecuteAtTime函数指针/变量/魔法代码片段,它允许我将任何旧函数传递给这个类。

此外,我希望在优先级队列中保存的事件按时间顺序排列事件并执行它们“携带”的功能。但是暂时忘掉了这个

像这样......

class Agent
{
    public:

    int id;
    float cash;

    Agent::Agent
    {
        cash = 100;
    }
}

class uberSystem
{
    public:

    float assets;
    int supplyOfDeadlyPoison;
    float poisonCost;

    std::vector<Agent> agents;

    uberSystem::uberSystem
    {
        assets = 100000;
        supplyOfDeadlyPoison = 100000;
        poisonCost = 8;

        for(int i = 0; i < 100; i++)
        {
        Agent newAgent;
        newAgent.id = i;
        agents.push_back(newAgent)
        }
     }
};


class Event
{
    public:

    int time;
    SOMETHING_THAT_LETS_ME_HOLD_FUNCTIONS myFunction;

    Event::Event(int t, SOMETHING_THAT_LETS_ME_HOLD_FUNCTIONS func)
    {
         time = t;
         myFunction = func;
    }
}

int uselessFunction()
{
    return 42;
}

void buyPoisonAndKillAgent(Agent &myAgent, uberSystem &mySystem)//obviously not good...
{
    myAgent.cash -= mySystem.poisonCost;
    mySystem.assets += mySystem.poisonCost;
    mySystem.agents.erase(mySystem.agents.begin()+myAgent.id);
    mySystem.supplyOfDeadlyPoison -= 1;
}


int main()
{

    uberSystem newSystem;
   // Event newEvent(100, uselessFunction());//make a new event
    Event newEvent(100, buyPoisonAndKillAgent(newSystem.agents[5], newSystem));
    newEvent.myFunction;//run the bloody function
    return 0;
}

好的,所以我现在打字就像是非常一厢情愿的想法。那么,我怎样才能做到这一点?函数指针是要走的路吗?还是有一些更好的方法,我有办法找不到?

哦,显然我确实有std::function可用......我一直都不在石器时代!

谢谢!

3 个答案:

答案 0 :(得分:2)

你可以有一个Base类事件(由@EdHeal提出),然后有一个模板子类存储你的函数指针:

class Event {
public:
  int time;
  Event(int t) : time(t) {}
  virtual ~Event(){}
  virtual void myFunction() = 0;
};

template<typename TFunc>
class TEvent : public Event {
public:
  TFunc func;
  TEvent(int t, TFunc f) : Event(t), func(f) {} 
  void myFunction() { func(); }
};

template<typename TFunc>
auto_ptr<Event> make_event(int time, TFunc func) {
    return std::auto_ptr<Event>(new TEvent<TFunc>(time,func));
}

使用辅助函数make_event,可以轻松调用并自动推断类型:

void useless() {std::cout << "Func A";}
struct functor {
  void operator()() {std::cout << "Functor B";} 
};

struct paramFunctor {
  paramFunctor(int x, double y): result(0), m_x(x), m_y(y){}

  void operator()() {
    std::cout << "Params: x:" << m_x << ", y:" << m_y << "\n";
  } 
  long long result;
private:
  int m_x;
  double m_y;
};

int main() {
  auto_ptr<Event> e1 = make_event(10,useless);
  auto_ptr<Event> e2 = make_event(100,functor());
  auto_ptr<Event> e2 = make_event(100,paramFunctor(1,2.0));

  // your code goes here

  e1->myFunction();
  e2->myFunction();
  e3->myFunction();

  return 0;
}

当然,如果可以访问C ++ 11(或TR1或者boost),根本不需要所有这些(正如其他答案所描述的那样)

答案 1 :(得分:1)

为什么不这样做

class Event {
    private:
       int time;
    public:
       Event(int t) : time(t)  { }
       virtual void DoEvent() = 0;
};

class MyEVent: public Event {
    public:
        MyEvent(int t) : Event(t) { }
        void DoEvent() { std::cout << "Event  called" << std::endl;
};

然后

int main() {

    MyEvent e(100);
    e.DoEvent();
    return 0;
}

这看起来更简单,您可以随意添加活动所需的任何数据。

对于列表,您使用Event指针,例如Event *e = new MyEvent(100)

答案 2 :(得分:1)

持有泛型函数或闭包的最简单方法是使用std::function;在没有C ++ 11 boost::function的情况下,它是一个很好的占位符。

这会产生:

class Event {
public:
private:
    std::time_t time;
    boost::function<void()> function;
}; // class Event

请注意,函数的签名需要精确处理:void()是一个不带参数且不返回任何内容的函数。

另外,请注意,只要其中一个operator()与预期签名匹配,就可以使用任意谓词,仿函数类或lambdas。