#include <iostream>
#include <vector>
#include <memory>

// Abstract base class: only defines area behavior and does not include any state constraints that could be violated
class Shape {
public:
    virtual double area() const = 0;
    virtual ~Shape() = default;
};

// Rectangle: has independent width and height
class Rectangle : public Shape {
    double width, height;
public:
    Rectangle(double w, double h) : width(w), height(h) {}
    double area() const override {
        return width * height;
    }
};

// Square: stores only the side length and is decoupled from Rectangle
class Square : public Shape {
    double side;
public:
    Square(double s) : side(s) {}
    double area() const override {
        return side * side;
    }
};

// Client code: depends on the abstract base class Shape
void printArea(const Shape& shape) {
    std::cout << "Area: " << shape.area() << std::endl;
}

int main() {
    Rectangle rect(3.0, 4.0);
    Square sq(5.0);

    // Derived objects can be safely substituted for base-class references
    printArea(rect);   // Output: Area: 12
    printArea(sq);     // Output: Area: 25

    // Use a container of base-class pointers to demonstrate runtime polymorphic substitution
    std::vector<std::unique_ptr<Shape>> shapes;
    shapes.push_back(std::make_unique<Rectangle>(2.0, 3.0));
    shapes.push_back(std::make_unique<Square>(4.0));

    for (const auto& s : shapes) {
        printArea(*s);
    }
    // Output:
    // Area: 6
    // Area: 16

    return 0;
}

results matching ""

    No results matching ""