Как построить Карту, где Ключ - это абстрактный базовый класс (не Значение) - PullRequest
0 голосов
/ 04 мая 2018

Я пытаюсь построить карту объектов, которые являются экземплярами различных производных классов, с базовым классом, являющимся абстрактным:

class B {void SomeMethod() = 0;}; //abstract
class D1 : public B {...}; // not abstract
class D2 : public B {...}; // not abstract
std::unordered_map<B,int> myMap;

D1 * d1 = new D1();
D2 * d2 = new D2();
myMap.insert({*d1,5}
myMap.insert({*d2,8}

Это не работает, потому что карта рассматривает *d1 B объект и пытается копировать-построить его внутри карты. даже если бы он работал, он нарезал бы объект, и данные D1 были бы потеряны. Пока я понимаю, почему это не может работать.

Но как мне сделать такую ​​карту?

  • хранение B* указателей вместо этого работает нормально, но тогда алгоритм хеширования карты сравнивает указатели , а не объекты, которые не найдут совпадение
  • Я не видел способа перезаписать оператор = (и его действительно не может быть, так как алгоритм хеширования работает с параметром, который является указателем - мне пришлось бы перезаписать сам алгоритм хеширования, чтобы разыменовать указатель.
  • обратите внимание, что C ++ коллекция абстрактных базовых классов не является дубликатом - она ​​говорит о Value ; Мне нужен абстрактный базовый класс в качестве Key , поэтому я могу find () it.

Другими словами, Вопрос :
Как я могу построить карту объектов (и затем искать их), где эти объекты являются экземплярами различных производных классов из общего базового класса?

1 Ответ

0 голосов
/ 04 мая 2018

Да, ваш второй вариант невозможен. Но твой первый! Контейнеры стандартной библиотеки позволяют использовать пользовательскую функцию хеширования, которую вы можете использовать в своих интересах.

Кроме того, вам в любом случае необходимо было бы предоставить пользовательскую хеш-функцию, так что это не должно быть проблемой. Также вы упомянули, что хотите иметь возможность искать их правильно? Ну, стандартная библиотека также позволяет вам настроить , что , и вы можете предоставить объект равенства ключей, который сравнивал бы базовые объекты, а не указатели.

struct FooPtrHash {
  std::size_t operator()(const Foo *Value) const {
    return Value->Value;
  }
};

struct FooPtrEquality {
  bool operator()(const Foo *Lhs, const Foo *Rhs) const {
    return *Lhs == *Rhs;
  }
};

std::unordered_map<Foo*, int, FooPtrHash, FooPtrEquality> Map;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...