Полиморфизм функций с типом ссылочных данных

У меня есть очередь, которая содержит объекты класса Event.

std::priority_queue<Event> events;

Но Event - это просто суперкласс реальных событий. Предположим, у нас есть следующие классы:

class Event{
   public:
     void Action(){
       std::cout<<"do nothing"<<std::endl;
     }
};

class XEvent : public Event{
   public:
     void Action(){ 
           std::cout<<"do x"<<std::endl;
     }

class YEvent : public Event{
   public:
     void Action(){
            std::cout<<"do y"<<std::endl;
     }
};

и в основной функции:

int main(){
  std::vector<Event> events;
  events.push_back(XEvent x);
  events.push_back(YEvent y);
  Event e = events[0];
  e.Action();
}

Я хочу, чтобы e.Action действовал в соответствии с переопределенной версией. (то есть "делай х").

Но вместо этого вывод дает мне "ничего не делать". Любое предложение?

PS На самом деле я ищу способ сделать это без использования указателей

3 ответа

Вставка в вектор копирует элемент. Тип цели всегда Event, заданный в качестве параметра для шаблона, поэтому это меняет тип.

Предложения:

  • Использовать std::function вместо. Это может быть именно то, что вы ищете для обработки событий.
  • Вместо этого используйте (умный) тип указателя, чтобы вы могли хранить полиморфные элементы.
  • Вместо этого используйте умный тип объединения / варианта, например Boost.Any или Boost.Variant (не уверен, что какой-либо из них уже стандартизирован).

Используйте смарт-указатель для общего указателя, попробуйте следующий код:

#include<iostream>
#include<vector>
#include <memory>

class Event{
   public:
     virtual void Action(){
       std::cout<<"do nothing"<<std::endl;
     }
};

class XEvent : public Event{
   public:
     void Action(){ 
           std::cout<<"do x"<<std::endl;
     }
};

class YEvent : public Event{
   public:
     void Action(){
            std::cout<<"do y"<<std::endl;
     }
};
int main(){
  std::vector<std::shared_ptr<Event>> events;
  events.push_back(std::make_shared<XEvent>());
  events.push_back(std::make_shared<YEvent>());
  std::shared_ptr<Event> e = events[0];
  e->Action();
  return 0;
}
class Event{
   public:
     virtual void Action(){
       std::cout<<"do nothing"<<std::endl;
     }
};

использовать виртуальную функцию, как указано выше, но вы создали объект, который из класса Event может быть, вы должны создать указатель;

int main(){
  std::vector<Event> events;
  events.push_back(XEvent x);
  events.push_back(YEvent y);
  XEvent xe = events[0];
  Event* e = &xe;
  e->Action();
}

или реализовать приведение объекта.

Другие вопросы по тегам