#include <iostream>
#include <cmath>
#include <memory>
#include <vector>
class ShapeVisitor;
class Shape {
public:
virtual ~Shape() = default;
virtual void accept(ShapeVisitor& visitor) = 0;
};
class Circle : public Shape {
public:
explicit Circle(double r) : radius(r) {}
double getRadius() const { return radius; }
void accept(ShapeVisitor& visitor) override;
private:
double radius;
};
class Rectangle : public Shape {
public:
Rectangle(double w, double h) : width(w), height(h) {}
double getWidth() const { return width; }
double getHeight() const { return height; }
void accept(ShapeVisitor& visitor) override;
private:
double width, height;
};
class ShapeVisitor {
public:
virtual ~ShapeVisitor() = default;
virtual void visit(Circle& circle) = 0;
virtual void visit(Rectangle& rectangle) = 0;
};
class AreaCalculator : public ShapeVisitor {
public:
void visit(Circle& circle) override {
double area = M_PI * circle.getRadius() * circle.getRadius();
std::cout << "Circle area: " << area << std::endl;
}
void visit(Rectangle& rectangle) override {
double area = rectangle.getWidth() * rectangle.getHeight();
std::cout << "Rectangle area: " << area << std::endl;
}
};
class DescriptionPrinter : public ShapeVisitor {
public:
void visit(Circle& circle) override {
std::cout << "This is a circle with radius "
<< circle.getRadius() << std::endl;
}
void visit(Rectangle& rectangle) override {
std::cout << "This is a rectangle with width "
<< rectangle.getWidth() << " and height "
<< rectangle.getHeight() << std::endl;
}
};
void Circle::accept(ShapeVisitor& visitor) {
visitor.visit(*this);
}
void Rectangle::accept(ShapeVisitor& visitor) {
visitor.visit(*this);
}
int main() {
std::vector<std::unique_ptr<Shape>> shapes;
shapes.push_back(std::make_unique<Circle>(5.0));
shapes.push_back(std::make_unique<Rectangle>(3.0, 4.0));
shapes.push_back(std::make_unique<Circle>(2.5));
AreaCalculator areaCalc;
DescriptionPrinter descPrinter;
std::cout << "=== Calculating areas ===" << std::endl;
for (auto& shape : shapes) {
shape->accept(areaCalc);
}
std::cout << "\n=== Printing descriptions ===" << std::endl;
for (auto& shape : shapes) {
shape->accept(descPrinter);
}
return 0;
}