// Inheritance hierarchy of 2 dimensional shapes #ifndef _SHAPE_H #define _SHAPE_H #include using namespace std; #include // Abstract base class for shapes class Shape { public: Shape(const char * n) : _name(n) { ++refs; } Shape(const Shape & s) : _name(s._name) { ++refs; } virtual ~Shape() { --refs; } // Pure virtual methods of Shape virtual double area() const = 0; virtual double perimeter() const = 0; virtual ostream & print(ostream & o) const = 0; virtual void resizeBy(double factor) = 0; const char * name() const { return _name; } static int refCount() { return refs; } private: const char * const _name; static int refs; // Reference counter of Shapes in existence }; // Overloaded output works for all Shapes inline ostream & operator << (ostream & o, const Shape & s) { return s.print(o); } // A Circle is a concrete type of Shape class Circle : public Shape { public: Circle(double r) : Shape("circle"), radius(r) { } virtual double area() const { return M_PI * radius * radius; } virtual double perimeter() const { return M_PI * 2 * radius; } virtual ostream & print(ostream & o) const { return o << name() << " with radius " << radius; } virtual void resizeBy(double factor) { radius *= factor; } private: double radius; }; // A Rectangle is a concrete type of Shape class Rectangle : public Shape { public: Rectangle(double w, double h) : Shape("rectangle"), width(w), height(h) { } virtual double area() const { return width * height; } virtual double perimeter() const { return 2 * (width + height); } virtual ostream & print(ostream & o) const { return o << name() << " of size " << width << " by " << height; } virtual void resizeBy(double factor) { width *= factor; height *= factor;} protected: double width, height; }; // A right Triangle is a concrete type of Shape class Triangle : public Shape { public: Triangle(double b, double h) : Shape("right triangle"), base(b), height(h) { } virtual double area() const { return base * height * .5; } virtual double perimeter() const { return (base + height + sqrt(base*base + height*height)); } virtual ostream & print(ostream & o) const { return o << name() << " of size " << base << " by " << height; } virtual void resizeBy(double factor) { base *= factor; height *= factor;} private: double base, height; }; // A Square is a concrete type of Rectangle class Square : public Rectangle { public: Square(double s) : Rectangle(s, s) { } virtual ostream & print(ostream & o) const { return o << "square " << name() << " of side " << width; } }; // A SquareHole is a Square with an enclosed Circle class SquareHole : public Square { public: SquareHole(double s) : Square(s), hole(s/2) { } // No destructor is necessary, but the destructor in the base class // must be virtual for the default destructor here to be used correctly virtual double area() const { return Square::area() - hole.area(); } virtual double perimeter() const { return Square::perimeter() + hole.perimeter(); } virtual ostream & print(ostream & o) const { return o << "square hole" << " of side " << width; } virtual void resizeBy(double factor) { Square::resizeBy(factor); hole.resizeBy(factor);} private: Circle hole; }; #endif