2012-05-24 3 views
2

Я пытаюсь использовать контейнер карты для хранения Shapes и сопоставить эти фигуры с идентификационным номером.C++, Boost: Как хранить объекты абстрактного типа в контейнере карты

До сих пор я всегда использовал контейнеры STL для хранения и управления памятью. Поэтому я хотел бы использовать контейнеры из этих видов:

std::map<int, Square> squares; 
std::map<int, Triangle> triangles; 
std::map<int, Circle> circles; 

Но я хочу, чтобы иметь одну карту, чтобы держать «Shapes», и это абстрактный базовый класс квадрат, треугольник и круг. Таким образом, чтобы достичь этого, я бы до сих пор храню реализуемый полученные объекты класса в своих картах, а затем другая карта:

std::map<int, Shape*> shapes; 

для хранения указателей на объекты, хранящихся в других картах.

Это кажется очень грязным, хотя, и я предпочел бы хранить все объекты в одной полиморфной карте, которая владеет и память управляет содержащимися объектами.

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

boost::ptr_map<int,Shape> shapes; 

Я получаю сообщение об ошибке: «Ошибка: не может выделить объект абстрактного типа" Shape»

Должен ли я сделать базовый класс реализуется? Это было бы немного взломать, поэтому я предпочел бы сделать это правильно, если будет такой способ.

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

std::map<int, boost::shared_ptr<Shape> > shapes; 

Это кажется такой простой цели, но так как я с таким трудом с ним я подозреваю, я Я пытаюсь сделать что-то, чего я не должен. Поэтому любой совет о том, где я мог бы пойти не так, очень ценится.

Спасибо.

+1

Ваше последнее предположение правильно. Исследуйте это. Если у вас есть более современный компилятор, а затем посмотрите на ['std :: unique_ptr'] (http://en.cppreference.com/w/cpp/memory/unique_ptr). –

+1

«У меня такое затруднение, я подозреваю, что я пытаюсь сделать то, что не должен». Итак ... с какими трудностями вы сталкиваетесь с этим? –

+0

Я имею в виду, что мне трудно понять, как хранить мои фигуры. Я бы ожидал, что вы легко найдете рекомендацию по рекомендациям онлайн, но после нескольких дней поиска я все еще теряюсь. Хотя, как предполагает Бенджамин, возможно, std :: map of shared_ptr или unique_ptr - это путь. – Pryo

ответ

1

Ваш базовый класс не может быть реализован. См. Пример здесь: http://www.boost.org/doc/libs/1_49_0/libs/ptr_container/doc/tutorial.html#associative-containers У животного там есть абстрактные функции! Фактически, это одно из основных применений для контейнеров ptr. Вероятно, ваша ошибка вызвана в другом месте, и вам нужно отправить больше кода.

также:

This seems very messy though, and I'd rather store all the objects in a single polymorphic map that owns and memory-manages the contained objects.

Я не думаю, что это. На самом деле может быть полезно никогда не «терять» тип фактического объекта, если вам это нужно позже. Например, если вы хотите сделать что-то для всех треугольников, но не для всех других форм, это пригодится.

Недостаток, конечно, заключается в том, что вам необходимо синхронизировать все карты, но это очень легко решить: вставьте эти 4 карты (и, желательно, нет других членов данных!) В частный раздел класса и выполните 3 перегрузки для разных типов и всегда вставлять их в строго типизированную «владеющую» карту и на карту с полиморфными указателями. Мне будет очень легко держать их в синхронизации за интерфейсом небольшого класса. Просто не пытайтесь делать это как неструктурированную часть чего-то большего, или код начнет выглядеть беспорядочным.

2

ptr_map<int, Shape> похоже на путь, и работает даже с абстрактным базовым типом (см. Пример here).Я предполагаю, что полученная вами ошибка исходит от использования operator[]. Действительно, как и в std::map, operator[] возвращает построенное по умолчанию значение, если ключ еще не был на карте. В этом случае он не может построить значение, так как Shape является абстрактным, следовательно, ошибкой компилятора.

Таким образом, вы можете использовать ptr_map, но не оператор индексирования. При вставке используйте insert, при поиске ключа используйте find.

Смежные вопросы