#c
#c
Вопрос:
У меня есть карта типа <lookup_ID, vector< parentclass *>> каждое местоположение на карте содержит вектор типа дочерний класс. Идея, лежащая в основе этой системы, заключается в возможности добавления дочернего элемента в связанную с ним карту с помощью функции add (parentclass *), и она сможет найти связанный с ней вектор дочернего типа. Я пытался использовать шаблоны и приведение, чтобы заставить вектор распознавать тип дочернего ввода в функцию добавления, но безуспешно. Я не хочу объявлять функцию add для каждого дочернего элемента parent, и независимо от того, как я это делал, мне приходилось объявлять функцию для каждого типа. Я мог бы удалить их из map, но опять же я остаюсь с проблемой вызова каждого дочернего элемента для любой функции, которую я хочу реализовать. Неужели у них нет способа сопоставить типы полиморфных структур с динамически распределяемыми списками?`
class Piece
{
public:
pieceType ID;
//...
}
class Infantry :
public Piece
{
public:
//...
};
class Artillery :
public Piece
{
public:
//...
};
//...
//In some other classes somewhere
std::map<pieceType, std::vector<Piece*>*> units;
units.emplace(Infantry_, new std::vector<Infantry*>);
units.emplace(Artillery_, new std::vector<Artillery*>);
//...
template<typename T>
std::vector<T*> operator (std::vector<T*> a, Piece * b) {
a.push_back(static_cast<T*>(b));
return a;
}
add(Piece * piece){
units.at(piece->ID) = units.at(piece->ID) piece;
}
Также я знаю, что в этом коде есть некоторые ошибки, это было больше для примера того, что я пытаюсь сказать.
Комментарии:
1. Приведенные ответы явно не указывают на это, но вы ищете некоторую форму того, что известно как самоанализ типа во время выполнения (RTTI). Проверьте документацию на TypeId.
Ответ №1:
Вы должны использовать виртуальную функцию, чтобы получить идентификатор для каждого дочернего класса
class Piece
{
public:
virtual PieceType ID() const = 0;
}
class Artillery
{
public:
virtual PieceType ID() const override { /* return your ID for Artillery */ }
}
class Infantery
{
public:
virtual PieceType ID() const override { /* return your ID for Infantery */ }
}
Ответ №2:
Между std::vector<Piece*>
и любым из std::vector<Infantry*>
или std::vector<Artillery*>
нет никакой связи, поэтому ваша карта может содержать только std::vector<Piece*>
s.
На это есть веская причина. Представьте, что у вас есть std::vector<Infantry*>
, и поместите указатель на него в свой std::map<pieceType, std::vector<Piece*>*>
. Затем вы могли бы вставить Artillery *
в это через map.
Вместо того, чтобы предоставлять std::vector<Piece*>
доступ напрямую, вы могли бы предоставить его представление (только для чтения), которое приводит к определенному подтипу.
Использование библиотеки ranges
auto asInfantry = ranges::view::transform([](Piece * p){ return static_cast<Infantry *>(p); });
auto asArtillery = ranges::view::transform([](Piece * p){ return static_cast<Artillery *>(p); });
class PieceMap
{
std::map<pieceType, std::vector<Piece*>> units;
public:
auto Infantry() { return units.at(Infantry_) | asInfantry; }
auto Artillery() { return units.at(Artillery_) | asArtillery; }
};