// Object-Oriented Modeling and Design // Example: Polymorphism and Design to Interface #include using std::cout; using std::endl; class GenericShape{ // Abstract base class public: virtual void draw()const = 0; // pure virtual function }; //*** Line class Line:public GenericShape{ // Line class public: Line(int in_x1, int in_y1, int in_x2, int in_y2) :m_x1{ in_x1 }, m_y1{ in_y1 }, m_x2{ in_x2 }, m_y2{ in_y2 } { } void draw() const override; // concrete draw function private: int m_x1, m_y1; // Coordinates of the endpoints of the line int m_x2, m_y2; }; // Draw of the Line void Line::draw()const { cout << "This is a line" << endl; cout << "Coordinates of endpoints: " << "X1=" << m_x1 << " ,Y1=" << m_y1 << " ,X2=" << m_x2 << " ,Y2=" << m_y2 << endl; } //*** Rectangle class Rectangle:public GenericShape{ // Rectangle class public: Rectangle(int in_x1, int in_y1, int in_x2, int in_y2) : m_x1{ in_x1 }, m_y1{ in_y1 }, m_x2{ in_x2 }, m_y2{ in_y2 } { } void draw()const override; // concrete draw private: int m_x1, m_y1; // coordinates of the corner point int m_x2, m_y2; }; // Draw of the Rectangle void Rectangle::draw()const { cout << "This is a rectangle" << endl; cout << "Coordinates of corner points: " << "X1=" << m_x1 << " ,Y1=" << m_y1 << " ,X2=" << m_x2 << " ,Y2=" << m_y2 << endl; } //*** Circle class Circle :public GenericShape { // Circle class public: Circle(int in_center_x, int in_center_y, int in_r) : m_center_x{ in_center_x }, m_center_y{ in_center_y }, m_radius{ in_r } { } void draw() const override; // concrete draw protected: int m_center_x, m_center_y; // coordinates of the center int m_radius; }; // Draw of the Circle void Circle::draw()const { cout << "This is a circle" << endl; cout << "Coordinates of center point: " << "X=" << m_center_x << " ,Y=" << m_center_y << endl; cout << "Radius: " << m_radius << endl; } /* !! Remove this line to add the Arc //** We can add this class later withot changing the client ****** class Arc :public Circle { // Arc class public: Arc(int in_center_x, int in_center_y, int in_r, int in_a1, int in_a2) :Circle{ in_center_x, in_center_y, in_r }, m_angle1{in_a1}, m_angle2{ in_a2 } { } void draw() const override; // concrete draw private: int m_angle1, m_angle2; // Start and end angles }; void Arc::draw()const { cout << "This is an arc" << endl; cout << "Coordinates of center point: " << "X=" << m_center_x << " ,Y=" << m_center_y << endl; cout << "Radius: " << m_radius << endl; cout << "Start and end angles: " << "SA=" << m_angle1 << " ,EA=" << m_angle2 << endl; } // */ /* A client (user) class that uses the Shape library, designed to interface (GenericShape) */ class Client { public: Client(GenericShape* inputShape) : m_shape{ inputShape } // Constructor {}; // initial shape // Change the shape in run-time void setShape(GenericShape* inputShape) { m_shape = inputShape; // shape points to another shape object } // Polymorphic show function void show() const { // Which draw function will be called? m_shape->draw(); // It is unknown at compile-time } private: GenericShape* m_shape; // shape pointer Can point to different shapes }; /** Test program **/ int main() { // Shape objects Circle* circle1 = new Circle{ 100, 100, 20 }; Rectangle* rectangle1 = new Rectangle{ 30, 50, 250, 140 }; Circle* circle2 = new Circle{ 300, 170, 50 }; // Client object Client testClient{ rectangle1 }; // Connect to rectangle1 testClient.show(); // get a service from the shape testClient.setShape(circle2); // change the shape to circle 2 testClient.show(); // get a service from the shape testClient.setShape(circle1); testClient.show(); /*!! Remove this line to add the Arc //** To test the Arc ******** Arc * arc = new Arc{ 100, 200, 50, 45, 90 }; testClient.setShape(arc); testClient.show(); // */ return 0; }