Pure virtual class and collections (vector?)

I am working on a graphical application that makes extensive use of virtual classes. He has:

  • An image class, which is essentially a collection of shapes.

  • A shape class that is purely virtual and has several classes that inherit it:

    • a circle
    • Polygon
    • Rectangle
  • The shape of a shape, which is any graphic shape (also virtual), inherits this shape.

Essentially, my problem boils down to implementing an image class, which is mainly used to store a collection of shapes. I am currently using Vector to store shapes, but obviously this is not the right solution, since Vector creates these shapes, which is not very good, since they are purely virtual.

Below is my current code base (short description):

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); } ... 

The error messages I receive are just one of them:

picture.cpp: 33: instance from Here /opt/local/bin/../lib/gcc/sparc-sun-solaris2.10/4.4.1/../../../../include/c++ /4.4.1/ext/new_allocator. h: 105: error: cannot select an object abstract type 'Shape' shape.h: 12: note: because the following virtual functions are clean in shape: shape.h: 58: note: virtual void Shape :: get (std :: istream &) shape.h: 31: note: virtual void Shape :: put (std :: ostream &) const shape.h: 36: note: virtual void Shape :: scale (const Point &, double) shape. h: 40: note: virtual void Shape :: translate (double, double) shape.h: 45: note: virtual void Shape :: reflectHorizontally (double) shape.h: 49: note: virtual void Form :: reflectVertically (double ) shape.h: 52: note: virtual RectangularArea Shape :: boundingBox () const shape.h: 21: note: virtual Shape * Shape :: clone () const shape.h: 55: note: virtual void Shape :: draw (Graphics &) const

So what is the ideal way to store these shapes. What collection should I use to store these things?

thanks

+7
c ++ vector virtual-inheritance virtual
source share
2 answers

When you need polymorphism, you need to use pointers or links. Since containers (or arrays) cannot store links, you should use pointers.

Essentially change the image class vector to:

 std::vector<Shape*> 

and amend other member functions accordingly.

The reason you cannot / should not store them as value types is because the vector is a homogeneous container, i.e. it stores only data of one type (and only one type - subclasses are not allowed!). The reason for this is because the vector stores its data in an array that must know the size of the stored objects. If the sizes of these objects are different (they can be for different shapes), then they cannot store them in an array.

If you store them as pointers, then they all have the same size ( sizeof(Shape*) ), and also have access to the vtable form, which allows polymorphic behavior.

+14
source share

Use covariant return types. See FAQ 20.8 for your clone methods. You can also use the factory method to create Shape objects.

In addition, you cannot have a container of abstract class objects; abstract classes cannot be created. Instead, create a container of pointers / references to derived concrete objects. Please note that if you use a pointer, your responsibility should be cleared. The container will not allocate memory correctly. You can use smart pointers instead of raw pointers to deal with this more efficiently. Find scoped_ptr and shared_ptr from Boost.

+1
source share

All Articles