2016-09-12 2 views
0
class Event{ 
public: 
     enum EventType { A_1, A_2, A_3, A_4}; 

     Event(EvtType type = A_1, double etime = 0.0) 
      : _type(type) 
      , _etime(etime) 
     {} 

     EventType get_Type() const { return _type; }; 
     double get_Time() const { return _etime; } 

protected: 
     EventType _type; 
     double _etime; 
}; 

struct EventLess{ 

    bool operator()(const Event& lhs, const Event& rhs) const 
     { 
     return (lhs.get_Time() > rhs.get_Time()); 
     } 
}; 

Я могу создать мин приоритетную очередь, как показано нижеприоритет очереди из нескольких классов C++

priority_queue<Event, std::vector<Event>, EventLess> q; 

Однако, если у меня есть еще один класс, как:

class Event1 
{ 
public: 
    enum EventType { disruption_1, disruption_2}; 

    Event(EvtType type = disruption_1, double htime = 0.0, double duration) 
      : _type(type) 
      , _htime(htime) 
      , _duration(duration) 

    {} 

    EventType get_Type() const { return _type; }; 
    double get_Time() const { return _htime; } 
    double get_Duration() const { return _duration; } 

protected: 
    EventType _type; 
    double _etime; 
    double _duration; 
}; 

и я хочу, чтобы создать мин приоритетная очередь этих двух классов (сравнение времени). Пожалуйста, кто-нибудь продемонстрирует мне, как решить эту проблему, будет благодарен.


После получения предложения, я улучшил код, используя наследование как представлено.

#include <queue> 
    #include <iostream> 
    using namespace std; 

    class IEvent{ 
    public: 
     IEvent(double time_e): Etime(time_e) {} 
     virtual double get_Time() const {return Etime;} 
    protected: 
     double Etime; 

    }; 

    class Event1:public IEvent{ 
    public: 
    enum EType1 { A_1, A_2, A_3, A_4}; 

    Event1(EType1 type1, double time_e, int _speed) 
    : _type1(type1) 
    , IEvent(time_e) 
    , speed(_speed) 
    {} 

    virtual EType1 get_Type() const { return _type1; }; 
    virtual double get_Time() const { return Etime; } 
    int get_speed() const {return speed;} 

    private: 
     EType1 _type1; 
     int speed; 
    }; 


    class Event2:public IEvent{ 
    public: 
    enum EType2 { disruption_1, disruption_2}; 

    Event2(EType2 type2, double time_e, double duration) 
    : _type2(type2) 
    , IEvent(time_e) 
    , _duration(duration) 
    {} 

    virtual EType2 get_Type() const { return _type2; }; 
    virtual double get_Time() const { return Etime; } 
    double get_duration() const { return _duration; } 

    private: 
     EType2 _type2; 
     double _duration; 

    }; 

    struct IEventLess{ 

      bool operator()(const IEvent& lhs, const IEvent& rhs) const 
      { 
      return (lhs.get_Time() > rhs.get_Time()); 
      } 
    }; 

    int main(){ 
      priority_queue<IEvent, vector<IEvent>, IEventLess> q; 

      q.push(Event1(Event1::A_1, 15.0, 10)); 
      q.push(Event2(Event2::disruption_1, 5.0, 5.0)); 

      IEvent *evt; 
      evt = new q.top(); 

      cout << evt.get_Type() << evt.get_Time() << endl; 

}

Тем не менее, я до сих пор есть некоторые проблемы в вызове другой функции в производном классе, и немного сбивает с толку при вызове функции верхней(), как показано в главной функции.

Пожалуйста, помогите мне решить проблему.

спасибо.

+0

Одним из способов может быть унаследована от общей базы и 'оператора <'. – user4581301

ответ

6

boost::variant устраняет необходимость общего базового класса или наследования:

#include <queue> 
#include <boost/variant.hpp> 

class Event{ 
public: 
    enum EventType { A_1, A_2, A_3, A_4}; 

    Event(EventType type = A_1, double etime = 0.0) 
    : _type(type) 
    , _etime(etime) 
    {} 

    EventType get_Type() const { return _type; }; 
    double get_Time() const { return _etime; } 

protected: 
    EventType _type; 
    double _etime; 
}; 

inline double get_time(const Event& e) { 
    return e.get_Time(); 
} 

class Event1 
{ 
public: 
    enum EventType { disruption_1, disruption_2}; 

    Event1(EventType type = disruption_1, double htime = 0.0, double duration = 0) 
    : _type(type) 
    , _etime(htime) 
    , _duration(duration) 
    {} 

    EventType get_Type() const { return _type; }; 
    double get_Time() const { return _etime; } 
    double get_Duration() const { return _duration; } 

protected: 
    EventType _type; 
    double _etime; 
    double _duration; 
}; 

inline double get_time(const Event1& e) { 
    return e.get_Time(); 
} 


// name predicates properly 
struct EventGreater{ 

    template<class L, class R> 
    bool operator()(const L& lhs, const R& rhs) const 
    { 
     return get_time(lhs) > get_time(rhs); 
    } 
}; 

template<class...Ts> 
double get_time(const boost::variant<Ts...>& var) 
{ 
    return boost::apply_visitor([](auto& x) { return get_time(x); }, var); 
} 

struct event_handler : boost::static_visitor<void> 
{ 
    void operator()(const Event& e) const 
    { 
     // handle an Event in here 
    } 

    void operator()(const Event1& e) const 
    { 
     // handle an Event1 in here 
    } 

}; 

int main() 
{ 
    using EventVariant = boost::variant<Event, Event1>; 
    // we all know that a priority queue inverts the predicate 
    std::priority_queue<EventVariant, std::vector<EventVariant>, EventGreater> q; 


    q.push(Event()); 
    q.push(Event1()); 

    // 
    // remove an item and action it 
    auto ev = std::move(q.top()); 
    q.pop(); 

    boost::apply_visitor(event_handler(), ev); 
} 
+0

Я попытался использовать boost. и у меня есть несколько вопросов. Нужно ли включать #include ? и когда я попытался построить, я получил массаж с ошибкой, показывая, что «нет подходящей функции для вызова в std :: priority queue ..... Не могли бы вы предложить мне, как решить эту проблему? Спасибо – Rocky

+0

@ Rocky в зависимости от вашей версии boost и/или C++ у вас может не быть поддержки лямбда. Возможно, вам понадобится создать небольшой функтор, полученный из boost :: static_visitor. В документах есть примеры. –

+0

Большое спасибо. он работает. Однако, можете ли вы продемонстрировать мне, как вывести верхний элемент из очереди в этом случае? Cheers – Rocky

2

Имейте оба Event и Event1 наследуйте от общей базы.

class IEvent 
{ 
public: 
    virtual double get_Time() = 0; 
}; 

class Event : public IEvent 
{ 
public: 
    virtual double get_Time() {...} 
} 

class Event1 : public IEvent 
{ 
public: 
    virtual double get_Time() {...} 
} 

Затем вы можете сохранить базовые указатели в очереди и при необходимости направить к конкретному ребенку.

std::priority_queue<std::shared_ptr<IEvent>, std::vector<IEvent>, IEventLess> q;

auto Time = q.front()->get_Time(); 
+1

, если вы собираетесь модифицировать классы для наследования, по крайней мере, make_Time отложить до общего виртуального имплантата и удалить динамические броски! –

+0

Можете ли вы добавить подходящее сравнение для этого? –

+0

@RichardHodges Обновлено, но с различными перечислениями «EventType» им все равно нужно «dynamic_cast». Хотя эти два перечисления, вероятно, можно было бы объединить в одну и в базу. – lcs