C++ Overridden method not getting called

17,860

Solution 1

Here's your problem:

struct ShapePointPair {
        Shape shape;
        Point location;
};

You are storing a Shape. You should be storing a Shape *, or a shared_ptr<Shape> or something. But not a Shape; C++ is not Java.

When you assign a Rect to the Shape, only the Shape part is being copied (this is object slicing).

Solution 2

This problem is called slicing - you lose the derived functionality when copying to a base. To avoid this use pointers to the base class, i.e.

std::vector<Graphics::Shape*> s;
s.push_back(&some_rect);

Solution 3

The problem is that in your vector you are storing copies of Shape objects, and copying a Shape object does not copy the data or functionality of its derived classes - you're slicing the polymorphism away.

Manage the objects using new and delete, and arrange for your vector to store pointers to them.

Solution 4

The polymorphism will only work from a pointer to a shape, not from a shape object.

Solution 5

You are accessing the shape object directly for the override to work you need to access the object via a pointer or references.

For example when you assigne the Shape into the ShapePointPair the code will 'slice' the object and only copy the Shape bit into the ShapePointPair

Doing this will mean you have to watch memory management - so you could use a smart pointer in the struct ShapePointPair { smart_pointer shape; Point location; };

Share:
17,860
Simon Moles
Author by

Simon Moles

Updated on June 10, 2022

Comments

  • Simon Moles
    Simon Moles almost 2 years

    Shape.h

    namespace Graphics {
        class Shape {
        public:
            virtual void Render(Point point) {};
        };
    }
    

    Rect.h

    namespace Graphics {
        class Rect : public Shape {
        public:
            Rect(float x, float y);
            Rect();
            void setSize(float x, float y);
            virtual void Render(Point point);
    
        private:
            float sizeX;
            float sizeY;
        };
    }
    
    struct ShapePointPair {
        Shape shape;
        Point location;
    };
    

    Used like this:

    std::vector<Graphics::ShapePointPair> theShapes = theSurface.getList();
    
    for(int i = 0; i < theShapes.size(); i++) {
        theShapes[i].shape.Render(theShapes[i].location);
    }
    

    This code ends up calling Shape::Render and not Rect::Render

    I'm assuming this is because it is casting the Rect to a Shape, but I don't have any idea how to stop it doing this. I'm trying to let each shape control how it is rendered by overriding the Render method.

    Any ideas on how to achieve this?