Чистый виртуальный класс и наборы (вектор?)

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

  • Класс изображения, который является по существу набором форм.

  • Класс форм, который является чисто виртуальным и имеет несколько классов, которые наследовались ему:

    • Круг
    • Полигон
    • Прямоугольник
  • Форма иллюстрации, которая является любым графическим числом (также виртуальный), форма, наследовалась этому.

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

Ниже моя текущая кодовая база (подвел итог немного):

class Figure {
public:
...
  virtual ~Figure();
...
};

class Shape: public Figure
{
public:
...
  virtual ~Shape() {}
  virtual Shape* clone() const = 0;
...
};

class Polygon : public Shape
{
public:
...
virtual Shape* clone() const {return new Polygon(*this);}
... 
private:
std::vector<Point> points;

};

class Picture: public Figure {
public:
...
  Picture(Graphics& gd);
  Picture (const Picture&);
  ~Picture();
  void clear();
  void add (const Shape&);
...
private:
std::vector<Shape> shapes;
Graphics* gfx;
};

//Picture implementation:
...
Picture::Picture(Graphics& gd)
{
gfx = &gd;
}


Picture::Picture(const Picture& a)
{
shapes = a.shapes;
}

Picture::~Picture() 
{
clear();
}

void Picture::clear()
{
shapes.clear();
}

void Picture::add (const Shape& shp)
{
Shape* nshp = shp.clone();
shapes.push_back(*nshp);
}
...

Сообщения об ошибках, которые я получаю, являются просто набором их:

изображение cpp:33: инстанцированный отсюда/opt/local/bin/../lib/gcc/sparc-sun-solaris2.10/4.4.1/../../../../include/c ++/4.4.1/ext/new_allocator.h:105: ошибка: не может выделить объект формы h:12 'Формы' абстрактного типа:примечание: потому что следующие виртуальные функции чисты в 'Форме': форма h:58:примечание: виртуальная пустая Форма:: доберитесь (станд.:: istream&) форма h:31:примечание: виртуальная пустая Форма:: помещенный (станд.:: ostream&) форма h:36 константы:примечание: виртуальная пустая Форма:: масштаб (константа Point&, дважды) форма h:40:примечание: виртуальная пустая Форма:: переведите (дважды, дважды) форму h:45:примечание: виртуальная пустая Форма:: reflectHorizontally (дважды) формируют h:49:примечание: виртуальная пустая Форма:: reflectVertically (дважды) формируют h:52:примечание: виртуальная Форма RectangularArea:: boundingBox () форма h:21 константы:примечание: виртуальная Форма* Форма:: клон () форма h:55 константы:примечание: виртуальная пустая Форма:: потяните константу (Graphics&)

Таким образом, что является идеальным способом сохранить эти формы. Какой набор я должен использовать для хранения этих вещей?

Спасибо

8
задан dirkgently 7 March 2010 в 00:05
поделиться

2 ответа

Когда вам нужен полиморфизм, вам нужно использовать либо указатели, либо ссылки. Поскольку контейнеры (или массивы) не могут хранить ссылки, вы должны использовать указатели.

По существу измените вектор вашего класса изображения на:

std::vector<Shape*>

и соответствующим образом измените другие функции-члены.

Причина, по которой вы не можете / не должны хранить их как типы значений, заключается в том, что вектор является однородным контейнером, т.е. он хранит данные только одного типа (и только одного типа - подклассы не являются разрешается!). Причина этого в том, что вектор хранит свои данные в массиве, которому необходимо знать размер хранимых им объектов. Если размеры этих объектов различны (а они могут быть для разных форм), то он не может хранить их в массиве.

Если вы храните их как указатели, тогда все они будут иметь одинаковый размер ( sizeof (Shape *) ), а также имеют доступ к vtable формы, что и обеспечивает полиморфное поведение.

17
ответ дан 5 December 2019 в 08:51
поделиться

Используйте ковариантные возвращаемые типы. См. FAQ 20.8 для получения информации о методах clone . Вы также можете полагаться на фабричный метод для создания объектов Shape .

Кроме того, у вас не может быть контейнера объектов абстрактного класса, абстрактные классы не могут быть созданы. Вместо этого создайте контейнер указателей / ссылок на производные конкретные объекты. Обратите внимание: если вы используете указатель, вы обязаны очистить их. Контейнер не освобождает память должным образом. Вы можете использовать интеллектуальные указатели вместо необработанных указателей, чтобы справиться с этим более эффективно. Найдите scoped_ptr и shared_ptr в Boost.

2
ответ дан 5 December 2019 в 08:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: