Search code examples
c++classinheritancederived-classdynamic-cast

Access by "a pointer of the base class" to a method or attribute of the child class which was not declared in the base class(dynamically)


during one of our assignments in C++ programming ( Inheritance), I had to design an abstract class Shape with some attributes like color, rotate degree and etc, Which are common between shapes. However, during the implementation of Base classes like Circle, Rectangle and ... I had to add some attributes like Center of the circle (which it self-required its own setter and getter cause it's private ! ) or 4 corners of the rectangle (with its setter and getter ) which were not mentioned as a function(whether virtual or not) in out Base class.

Originally I wanted to have access to every method of derived class using a pointer of the base class.In my main, I used a Pointer of my base class, Shape * to have a Dynamic Bind to the common methods and attributes, but when it comes to setting the separate (uncommon between derived and base) attributes, it's not accessible via Pointer of the base class. I tried to declare them as virtual functions in my Base class, however, it doesn't work and it's also illogical, as the user might have many characteristics in one shape! Does any one have any idea how can this problem be solved? and how can I have access to those mentioned methods and attributes that are only declared in the Derived class, using Shape*? tnx

this is my base class for shapes.

class Shape
{
public:
    virtual void set_color(int color)=0;
    virtual void set_border_color(int border_color)=0;
    virtual void set_degree(float border_width)=0;
    virtual void set_border_width(double rotate_degree)=0;
    virtual void set_opacity(double opacity)=0;


protected:
    int color;
    int border_color;
    float border_width;
    double rotate_degree;
    double opacity;

};

respectively are my Circle and Rectangle class

circle Header:

#ifndef CIRCLE_H
#define CIRCLE_H
#include "shape.h"



class Circle :public Shape
{
public:
     void set_color(int _color);
     void set_border_color(int _border_color);
     void set_degree(float rotate_degree);
     void set_border_width(double border_width);
     void set_opacity(double _opacity);

    virtual void set_x_center(int _x_center);
    virtual void set_y_center(int _y_center);
    virtual void set_radius(int _radius);
    virtual void set_name(std ::string _name);
     int get_color();
     int get_x_center();
     int get_y_center();
     std::string get_name();

private:

    int x_center;
    int y_center;
    int radius;
    std ::string name;

};

#endif // CIRCLE_H

circle CPP:

#include <sstream>
#include <iostream> 
#include <algorithm>
#include <string>
#include "circle.h"
#include "shape.h"


     void Circle::set_color(int _color){ color=_color;}
     void Circle::set_border_color(int _border_color){border_color=_border_color;}
     void Circle::set_degree(float _rotate_degree){rotate_degree=_rotate_degree;}
     void Circle::set_border_width(double _border_width){border_width=_border_width; }
     void Circle::set_opacity(double _opacity){opacity=_opacity;}
     int Circle::get_color(){return color;}

     void Circle::set_x_center(int _x_center){ x_center=_x_center;}
     void Circle::set_y_center(int _y_center){ y_center=_y_center;}
     void Circle::set_radius(int _radius){ radius=_radius;}
     void Circle::set_name(std ::string _name){ name=_name;}


     int Circle::get_x_center(){return x_center;}
     int Circle::get_y_center(){return y_center;}
     std::string Circle::get_name(){return name;}

rectangle HEADER:

#ifndef RECT_H
#define RECT_H
#include <sstream>
#include <iostream> 
#include <algorithm>
#include <string>
#include "rect.h"
#include "shape.h"


class Rect : public Shape
{
public:
     void set_color(int _color);
     void set_border_color(int _border_color);
     void set_degree(float _border_width);
     void set_border_width(double _rotate_degree);
     void set_opacity(double _opacity);
     void set_first_point(int _first_x,int _first_y);
     void set_second_point(int _second_x,int _second_y);
     void set_name(std ::string _name);
private:

    int first_point [2];

    int second_point [2];
    std ::string name;

};



#endif // RECT_H

rectangle CPP:

#include "rect.h"
#include "shape.h"


void Rect::set_color(int _color){ color=_color;}
void Rect::set_border_color(int _border_color){border_color=_border_color;}
void Rect::set_degree(float _border_width){border_width=_border_width;}
void Rect::set_border_width(double _rotate_degree){rotate_degree=_rotate_degree;}
void Rect::set_opacity(double _opacity){opacity=_opacity;}


void Rect::set_first_point(int _first_x,int _first_y){first_point[0]=_first_x;first_point[1]=_first_y;}
void Rect::set_second_point(int _second_x,int _second_y){second_point[0]=_second_x;second_point[1]=_second_x;}

void Rect::set_name(std ::string _name){name=_name;}

and here is my main

#include <cstdlib>
#include <vector>
#include <cmath>
#include <string>
#include <vector>
#include <cmath>
#include <sstream>
#include <iostream> 
#include <algorithm>
#include "shape.h"
#include "circle.h"
using namespace std;

int main()
{
Circle a;
Shape* b;
b=&a;

b->set_color(12);
b->set_x_center(30);
cout<< b->get_x_center();
return 0 ;
}

Originally I wanted to have access to every method of derived class using a pointer of the base class.


Solution

  • You can do so by dynamic casting back to the Circle *:

    b->set_color(12);
    dynamic_cast<Circle *>(b)->set_x_center(30);
    std::cout << dynamic_cast<Circle *>(b)->get_x_center();
    

    This works already, however, when dynamic casting like this make sure the result is not a nullptr

    b->set_color(12);
    Circle *c = dynamic_cast<Circle *>(b);
    if (c != nullptr)
    {
        c->set_x_center(30);
        std::cout << c->get_x_center();
    }