2014-10-03 54 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表達式。