2014-10-03 46 views
2

因此,我首先进行了合理的Google搜索,但所有解决方案都显得过于复杂。所以,我想我会在这里问,看看这个任务是否真的需要我遇到过的那种方法...如何实现一个简单的事件队列?

因此,说我有一个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可用......毕竟我并没有处于石器时代!

谢谢!

+0

那么[std :: deque >](http://en.cppreference.com/w/cpp/container/deque)呢? – 2014-10-03 08:24:48

+1

std :: function可以做到这一点,我建议你避免函数指针。 :) – Melkon 2014-10-03 08:27:34

+0

“时间”是实时的还是模拟的?或者它只是用来订购事件? – MatthiasB 2014-10-03 08:30:00

回答

2

你可以有一个基类的事件(如提出@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,或升压)没有必要为这一切在所有(如其他答案描述)

+0

你可以使用智能指针吗? :) – 2014-10-03 08:47:35

+0

@MatthieuM。我会的,但问题要求stoneage - preC++ 11解决方案;) – MatthiasB 2014-10-03 08:49:49

+0

那么? 'std :: auto_ptr'和'boost :: scoped_ptr'完全兼容C++ 03。 'boost :: shared_ptr'也在那里工作。只有'std :: unique_ptr'由C++ 11的新特性(特别是移动语义)成为可能。 – 2014-10-03 08:56:48

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)

+0

其实看起来不错! – Argh 2014-10-03 08:29:26

1

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

这产生了:

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

注意函数的签名需要被一种高精度:void()是一个功能不采取任何参数并返回什么。

此外,请注意,只要其中一个operator()与预期签名匹配,您就可以使用任意谓词,函子类或lambda表达式。