Search code examples
c++classobjectpolymorphismvirtual

virtual class and polymorphism


class Shape
{
public:
  Shape() {size=0;}
  virtual bool isequal(const Shape& rhs){return false;};
  int size;
};

I have two classes (Rectangle and Cirle) which inherit from a class shape.

class Circle : public Shape
{
public:
  // snip
  Circle(int size): size(size) {}
  Circle(const Circle & rhs): size(rhs.size){}
  bool isequal( Shape &rhs)
  {
    Circle* rhsAsCircle = dynamic_cast<Circle*>(&rhs);
    if(rhsAsCircle == nullptr)
       return false; // not a Circle; can't be equal
    return size==rhsAsCircle->size;
  }
  int size;
};
class Rectangle : public Shape
{
public:
  Rectangle(int size1,int size2): size1(size1),size2(size2) {}
  Rectangle(const Rectangle & rhs): size1(rhs.size1),size2(rhs.size2) {}
  bool isequal( Shape &rhs)
  {
    Rectangle* rhs2 = dynamic_cast<Rectangle*>(&rhs);
    if(rhs2 == nullptr)
       return false; // not a Rectangle; can't be equal
    return (size1==rhs2->size1 && size2==rhs2->size2);
  }
  int size1;
  int size2; 
};

I use a class P to store different shapes in a vector and perform different operationg (ex adding rectangles/circles, deleting rectangles/circles.

class P
{
public:
  P(){}
  bool add(Rectangle rhs)
  {
    uint i=0;
    while (i<v.size() && rhs.isequal(*v[i])==false)
      i++;
    if (i!=v.size())
      return false;
    v.push_back(new Rectangle(rhs));
    return true;
  }
  bool add(Circle rhs)
  {
    uint i=0;
    while (i<v.size() && rhs.isequal(*v[i])==false)
      i++;
    if (i!=v.size())
      return false;
    v.push_back(new Circle(rhs));
    return true;
  }
  vector<Shape*> v;
};

To add a shape (rectangle or circle) I had to overload the function add. Isn't there a way to do only one function? Because circles and rectangle are shapes, no?


Solution

  • You could just pass the base class Shape to the add function. Just pass a pointer to the object to store it inside your vector vector<Shape*> v;

      bool add(Shape *shape)
      {
        uint i = 0;
    
        for( i = 0; i < v.size(); i++ ) {
          if(shape.isequal(*v[i]) == true)
            return false;
        }
    
        if ( i != v.size() )
          return false;
    
        v.push_back(shape);
    
        return true;
      }
    

    Here is how this would work:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    class Shape
    {
    protected:
        int m_size;
    public:
        int getSize() { return m_size; }
    
        virtual bool isEqual(Shape *rhs) = 0;
    };
    
    class Rectangle : public Shape 
    {
    private:
        int m_size2;
    public:
        Rectangle(int size, int size2) { m_size = size; m_size2 = size2; }
    
        int getSize2() { return m_size2; }
    
        bool isEqual(Shape *rhs)
        {
            Rectangle* rectangle = dynamic_cast<Rectangle*>(rhs);
    
            if(rectangle == 0)
                return false; // not a Rectangle
    
            return m_size == rectangle->getSize() && m_size2 == rectangle->getSize2();
        }
    };
    
    class Circle : public Shape
    {
    public:
        Circle(int size) { m_size = size; }
    
        bool isEqual(Shape *rhs)
        {
            Circle* circle = dynamic_cast<Circle*>(rhs);
    
            if(circle == 0)
                return false; // not a Circle
    
            return m_size == circle->getSize();
        }
    };
    
    class Container
    {
    private:
        vector<Shape*> v;
    public:   
        ~Container()
        {
            for(int i = 0; i < v.size(); i++) {
                cout << "Removind element Nr. " << i << endl;
                delete v[i];
            }
            v.erase(v.begin(), v.end());
        }
    
        bool add(Shape *shape) 
        {
            for(int i = 0; i < v.size(); i++) {
    
                if( v[i] == shape ) { 
                    cout << "  Element rejected (tried to add same element twice)" << endl;
                    return false;
                }
    
                if( v[i]->isEqual(shape) ) {
                    cout << "  Element rejected (an element with size " << v[i]->getSize() << " was already inside that list" << endl;
                    return false;
                }
    
            }
    
            cout << "  Adding Element" << endl;
            v.push_back(shape);
            return true;
        }
    
        void print()
        {
            for(int i = 0; i < v.size(); i++) {
                cout << "Size of element " << i << ": " << v[i]->getSize() << endl;
            }
        }
    };
    
    int main()
    {
       Rectangle *r        = new Rectangle(1, 2);
       Circle *c           = new Circle(2);
       Circle *c_reject    = new Circle(2);
       Rectangle *r_reject = new Rectangle(1, 2);
    
       Container container;
       container.add(r);
       container.add(c);
    
       container.add(r);        // will be rejected because r was already added
       container.add(c_reject); // will be rejected 
       container.add(r_reject); // will be rejected too
    
       container.print();
    
       return 0;
    }