Полиморфизм функций с типом ссылочных данных
У меня есть очередь, которая содержит объекты класса 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();
}
или реализовать приведение объекта.