0

I've been trying to understand C++ inheritance and polymorphism a little bit better. But I'm having a really hard time getting this to work.

I have a base class called Shape. I have Rectangle that is child of Shape. And Square that is child of Rectangle.

Shape has no area. Rectangle and Square have area equal to width*height.

Setting width and height for Rectangle is independent. In the case of Square, when setting width or height, the function will set both attributes to the same value. Unfortunately that is not what is happening if I try to use polymorphism by creating a Square on a Rectangle.


shapes.hpp:

#ifndef SHAPES_H
#define SHAPES_H

// Base class
class Shape {
    public:
        virtual void setWidth(int w);
        virtual void setHeight(int h);
    protected:
        int width;
        int height;
};

// Derived class
class Rectangle: public Shape {
   public:
      int getArea();
};

class Square: public Rectangle {
   public:
      void setWidth(int w) override;
      void setHeight(int h) override;
};

#endif /* SHAPES_H */

shapes.cpp:

#include "shapes.hpp"

// Base class
void Shape::setWidth(int w) {
    width = w;
}
void Shape::setHeight(int h) {
    height = h;
}

// Derived class
int Rectangle::getArea() { 
    return (width * height); 
}

// Overloading
void Square::setWidth(int w) {
    width = w;
    height = w;
}
void Square::setHeight(int h) {
    width = h;
    height = h;
}

Testing the getArea() functions:

    Shape rect = Rectangle();
    rect.setHeight(7);
    rect.setWidth(5);
    //I had to cast the Rectangle so it would be able to call getArea()
    cout << "Total rectangle area (w5xh7): " << ((Rectangle*)&rect)->getArea() << endl;
    Rectangle square = Square();
    square.setHeight(7);
    square.setWidth(5);
    //I would like to be able to call Square's getArea() without having to cast it.
    cout << "Total square area (w5xh7): " << square.getArea() << endl;

I had to cast the Rectangle so it would be able to call getArea(). I would like to be able to call Square's getArea() without having to cast it. Is that possible?

Thank you.

CFlux
  • 346
  • 4
  • 9
  • 2
    Your design seems odd. Why shouldn't `Shape` have `getArea`? And why isn't `Rectangle` inheriting `setHeight` and `setWidth`? – cigien Oct 17 '20 at 20:33
  • `Shape rect = Rectangle();` -- you sliced your object. See the linked quesiton for more information. Any attempt to cast `rect` back to a `Rectangle`, as the shown code tries to do, will only result [in demons flying out of your nose](http://www.catb.org/jargon/html/N/nasal-demons.html). C++ does not work this way. This is how objects might work in Java, but C++ is not Java. – Sam Varshavchik Oct 17 '20 at 20:36
  • 1
    Funny design that. "Area" is a `Shape` concept. Width and height are pertinent only to a rectangle, which should be directly inherited from Shape. "Length" is pertinent to a square which should, again be directly inherited from Shape. Doing it my way means you could introduce a Circle without messing up your existing code. Do you really need all those "setters"? Setter functions are for Java programmers who don't know what they are doing. Use a constructor and be done with it. – Bathsheba Oct 17 '20 at 20:36
  • In geometry a square is a type of rectangle. In object-oriented polymorphism, a square is not a rectangle, because a square violates a rectangle's contract for what it means to be a rectangle. But as a learning exercise, you can ignore that for now. (A concrete class deriving from a concrete class is a bit of a code smell anyway.) – Eljay Oct 17 '20 at 20:39
  • The ideas behind the odd design is to make the exercise harder. It's a "what if" situation. That is the same reason for the setters. "What if a function ends up changing some attributes?". It doesn't need to be a setter, the same way we could be talking about other things other than shapes. This is just an exercise. – CFlux Oct 17 '20 at 20:45
  • If attributes change then just rebuild the object. – Bathsheba Oct 17 '20 at 20:49

0 Answers0