Listing 4 The shape class hierarchy with virtual cloning functions employing the relaxed return type rules

#include <iostream.h>
#include <math.h>
#include <stddef.h>

//
// base class 'shape'
//
class shape
   {
public:
   enum palette { BLUE, GREEN, RED };
   shape(palette c);
   virtual double area() const = 0;
   virtual shape *clone() const = 0;
   palette_color() const;
   virtual const char *name() const = 0;
   virtual ostream &put(ostream &os) const;
private:
   palette_color;
   static const char *color_image[RED - BLUE + 1];
   };

const char *shape::color_image[shape::RED - shape::BLUE + 1] =
   { "blue", "green", "red" };
   
shape::shape(palette c) : _color(c) { }

ostream &shape::put(ostream &os) const
   {
   return os << color_image[color()] << ' ' << name();
   }

shape::palette shape::color() const
   {
   return_color;
   }

//
// class 'circle' derived from 'shape'
//
const double pi = 3.1415926;

class circle : public shape
   {
public:
   circle(palette c, double r);
   double area() const;
   circle *clone() const;
   const char *name() const;
   ostream &put(ostream &os) const;
private:
   double radius;
   };

circle::circle(palette c, double r) : shape(c), radius(r) { }

double circle::area() const
   {
   return pi * radius * radius;
   }
   
const char *circle::name() const
   {
   return "circle";
   }

ostream &circle::put(ostream &os) const
   {
   return shape::put(os) << "with radius = " << radius;
   }

circle *circle::clone() const
   {
   return new circle(*this);
   }

//
// class 'rectangle' derived from 'shape'
//
class rectangle: public shape
   {
public:
   rectangle(palette c, double h, double w);
   double area() const;
   rectangle *clone() const;
   const char *name() const;
   ostream &put(ostream &os) const;
private:
   double height, width;
   };

rectangle::rectangle(palette c, double h, double w)
   : shape(c), height(h), width(w) { }

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

const char *rectangle::name() const
   {
   return "rectangle";
   }

ostream &rectangle::put(ostream &os) const
   {
   return shape::put(os) << "with height = " << height
      << " and width = " << width;
   }

rectangle *rectangle::clone() const
   {
   return new rectangle(*this);
   }

//
// class 'triangle' derived from 'shape'
//
class triangle : public shape
   {
public:
   triangle(palette c, double s1, double s2, double a);
   double area() const;
   triangle *clone() const;
   const char *name() const;
   ostream &put(ostream &os) const;
private:
   double side1, side2, angle;
   };

triangle::triangle(palette c, double s1, double s2, double a)
   : shape(c), side1(s1), side2(s2), angle(a) { }
   
double triangle::area() const
   {
   return side1 * sin(angle) * side2 / 2;
   };

const char *triangle::name() const
   {
   return "triangle";
   }

ostream &triangle::put(ostream &os) const
   {
   return shape::put(os) <<" with one side =" << side1
      << ", another side =" << side2
      <<" and angle = " << angle;
   }
   
triangle *triangle::clone() const
   {
   return new triangle(*this);
   }

ostream &operator<<(ostream &os, const shape &s)
   {
   return s.put(os);
   }

// End of File