After doing some researches I can not seem to find a simple example resolving a problem I encounter often.

Let's say I want to create a little application where I can create Squares, Circles, and other shapes, display them on a screen, modify their properties after selecting them, and then compute all of their perimeters.

I would do the model class like this :

    class AbstractShape
    {
    public :
        typedef enum{
            SQUARE = 0,
            CIRCLE,
        } SHAPE_TYPE;
        
        AbstractShape(SHAPE_TYPE type):m_type(type){}
        virtual ~AbstractShape();
    
        virtual float computePerimeter() const = 0;
        
        SHAPE_TYPE getType() const{return m_type;}
    protected :
        const SHAPE_TYPE  m_type;
    };
    
    class Square : public AbstractShape
    {
    public:
        Square():AbstractShape(SQUARE){}
        ~Square();
    
        void setWidth(float w){m_width = w;}
        float getWidth() const{return m_width;}
    
        float computePerimeter() const{
            return m_width*4;
        }
    
    private :
        float m_width;
    };
    
    class Circle : public AbstractShape
    {
    public:
        Circle():AbstractShape(CIRCLE){}
        ~Circle();
    
        void setRadius(float w){m_radius = w;}
        float getRadius() const{return m_radius;}
    
        float computePerimeter() const{
            return 2*M_PI*m_radius;
        }
    
    private :
        float m_radius;
    };

(Imagine I have more classes of shapes : triangles, hexagones, with each time their proprers variables and associated getters and setters. The problems I faced had 8 subclasses but for the sake of the example I stopped at 2)

I now have a ShapeManager, instanciating and storing all the shapes in an array :

    class ShapeManager
    {
    public:
        ShapeManager();
        ~ShapeManager();
    
        void addShape(AbstractShape* shape){
            m_shapes.push_back(shape);
        }
    
        float computeShapePerimeter(int shapeIndex){
            return m_shapes[shapeIndex]->computePerimeter();
        }
    
    
    private :
        std::vector<AbstractShape*> m_shapes;
    };

Finally, I have a view with spinboxes to change each parameter for each type of shape. For example, when I select a square on the screen, the parameter widget only displays Square-related parameters (thanks to *AbstractShape::getType()*) and proposes to change the width of the square.
To do that I need a function allowing me to modify the width in *ShapeManager*, and this is how I do it :

    void ShapeManager::changeSquareWidth(int shapeIndex, float width){
       Square* square = dynamic_cast<Square*>(m_shapes[shapeIndex]);
       assert(square);
       square->setWidth(width);
    }

Is there a better design avoiding me to use the dynamic_cast and to implement a getter/setter couple in ShapeManager for each subclass variables I may have ? I already tried to use [template but failed][1].


  [1]: https://stackoverflow.com/questions/38636730/reimplement-a-virtual-function-from-base-class-in-a-derived-template-class