#include <iostream>
#include <string>
#include <cmath>

// Base class: abstract shape
class Shape {
protected:
    std::string color;
public:
    Shape(const std::string& c) : color(c) {
        std::cout << "Shape constructor (color: " << color << ")" << std::endl;
    }

    virtual ~Shape() {
        std::cout << "Shape destructor" << std::endl;
    }

    // Pure virtual function, makes Shape an abstract base class that cannot be instantiated
    virtual double area() const = 0;

    std::string getColor() const {
        return color;
    }

    virtual void display() const {
        std::cout << "This is a shape, color: " << color << std::endl;
    }
};

// Derived class: circle
class Circle : public Shape {
private:
    double radius;
public:
    Circle(const std::string& c, double r) : Shape(c), radius(r) {
        std::cout << "Circle constructor (radius: " << radius << ")" << std::endl;
    }

    ~Circle() override {
        std::cout << "Circle destructor" << std::endl;
    }

    double area() const override {
        return M_PI * radius * radius;
    }

    void display() const override {
        std::cout << "Circle, color: " << color << ", radius: " << radius
                  << ", area: " << area() << std::endl;
    }
};

// Derived class: rectangle
class Rectangle : public Shape {
private:
    double width, height;
public:
    Rectangle(const std::string& c, double w, double h) : Shape(c), width(w), height(h) {
        std::cout << "Rectangle constructor (width: " << width << ", height: " << height << ")" << std::endl;
    }

    ~Rectangle() override {
        std::cout << "Rectangle destructor" << std::endl;
    }

    double area() const override {
        return width * height;
    }

    void display() const override {
        std::cout << "Rectangle, color: " << color << ", width: " << width
                  << ", height: " << height << ", area: " << area() << std::endl;
    }
};

int main() {
    std::cout << "=== Demonstrating C++ Inheritance (Abstract Base Class Version) ===\n" << std::endl;

    // 1. Create derived class objects, observe constructor/destructor order
    std::cout << "--- Creating Circle object ---" << std::endl;
    Circle circle("red", 5.0);
    std::cout << "\n--- Creating Rectangle object ---" << std::endl;
    Rectangle rect("blue", 4.0, 6.0);

    std::cout << "\n--- Derived class objects call member functions directly ---" << std::endl;
    circle.display();
    rect.display();

    // 2. Polymorphism: call overridden functions through base class pointers
    std::cout << "\n--- Polymorphism demonstration (base class pointer array) ---" << std::endl;
    Shape* shapes[2];
    shapes[0] = &circle;
    shapes[1] = &rect;

    for (int i = 0; i < 2; ++i) {
        shapes[i]->display();               // Dynamic binding, calls derived class version
        std::cout << "Area calculation: " << shapes[i]->area() << std::endl;
    }

    // 3. Access protected members (through public interface provided by base class)
    std::cout << "\n--- Accessing protected members (through public interface) ---" << std::endl;
    std::cout << "Circle color is: " << circle.getColor() << std::endl;

    // 4. Polymorphism with base class reference (no object slicing)
    std::cout << "\n--- Polymorphism with base class reference ---" << std::endl;
    Shape& shapeRef = rect;
    shapeRef.display();         // Calls Rectangle::display()

    // Note: Cannot create Shape object because Shape is abstract
    // Shape illegal;  // Error! Cannot instantiate abstract class

    std::cout << "\n--- Program ending, objects will be destructed (reverse order of construction) ---" << std::endl;
    return 0;
}

results matching ""

    No results matching ""