Listing 3 The complete frog pond program

// main.cpp - Frog Pond Listing 3
#include <frog.h>

main()
   {
   PMF_VV pf = &Creature::move; // bound to a virtual
   Pond walden;
   Creature *p1;
   Creature *p2;
   
   p1 = Creature::newCreature(Tadpole("Wiggly") );
   walden.insert(p1);
   p2 = Creature::newCreature(Bullfrog("Croaker") );
   walden.insert(p2);
   
   cout << "First time ------------------\n";
   walden.activate( pf ); // Tell all creatures to move
   cout << "second time -----------------\n";
   walden.activate( pf ); // Tell all creatures to move
   cout << "third time ------------------\n";
   walden.activate( pf ); // Tell all creatures to move
   
   return 0;
   }
   
First time --------------------
WigglyAge 1 Swimming jerkily
Croaker - I'm jumping
second time -------------------

Wiggly Age 2 Swimming jerkily still, but changing into Bullfrog
Croaker - I'm jumping
third time --------------------
Wiggly - I'm jumping
Croaker - I'm jumping
//  Frog.h
#ifndef FROG_H
#define FROG_H
#include <iostream.h>
#finclude <rw/gslist.h>

class Creature
   {
public:
   Creature(Creature *ptr);
   Creature(const Creature &c) : object(c.object) {}
   virtual void move();
   virtual Creature *clone() const;
   static Creature *newCreature(const Creature&);
   virtual const char *getname() const
      {return object->getname(); }
   virtual ~Creature();
//    void change(Creature *c);
protected:
   Creature() { object = 0; }  // invoked by derived
   Creature *object;
   static Creature *altered;
   };
   
declare(GSlist,Creature)

class Frog : public Creature
   {
protected:
   const char *name;
public:
   Frog(const char *p);
   Frog(const Frog &f);
   ~Frog();
   virtual void move() = 0;
   virtual const char *getname() const { return name; }
   Creature * clone() const;
   };
   
class Tadpole : public Frog
   {
   int age;
public:
   Tadpole(const char *name = "Noname Tadpole");
   void move();
   Tadpole(const Tadpole& t) : Frog(t), age(t.age) { }
       // invoke Frog copy ctor
   Creature * clone() const;
   };
   
class Bullfrog : public Frog
   {
public:
   Bullfrog(const char *name="Noname frog");
   Bullfrog(const Bullfrog &b) : Frog(b) {}
   void move() {cout << name <<" - I'm jumping\n"; }
   Creature * clone() const { return new Bullfrog(*this); }
   
class Pond
   {
   GSlist(Creature) list; // singly linked creature list
public:
   void activate( void (Creature::*pf) () );
   void insert(Creature*);
   };
typedef void (Creature::*PMF_VV)();
#endif
// Frog.cpp
#include <stdlib.h>
#include <frog.h>
#include <string.h>

Creature *Creature::altered = 0;  // private static data
void Pond::insert(Creature *f)
   {
   list.insert(f);
   }
   
void Pond::activate( PMF_VV pmf_vv )
   {
   GSlistIterator(Creature) it(list);
   Creature *resident;
   while ( resident = (Creature *)it() )
      {
      (resident->*pmf_vv)();
      }
   }
   
Creature *Creature::newCreature(const Creature& prototype)
   {
   Creature *C = new Creature(prototype.clone());
   // we must return an envelope, clone just makes a letter
   return C;
   }
   
Creature * Tadpole::clone() const
   {
   Tadpole *t = new Tadpole(*this); // Tadpole copy ctor
   return t;
   }
   
Creature::Creature(Creature *objptr)
   {
   object = objptr;
   }
   
Creature::~Creature() { }

Creature *Creature::clone() const
   {
   Creature *p = object->clone();
   Creature *envelope = new Creature(p);
   return envelope;
   }
   
void Creature::move()
   {
   object->move();
   if ( altered )
      {
      delete object;
      object = altered;
      altered = 0;
      }
   }
   
Creature * Frog::clone() const  // never get here
   {
   return 0;
   }
   
Frog::Frog(const char *n) : name(n) { }

Frog::Frog(const Frog &f) : Creature(f), name (f.getname())
   {
   }
   
Tadpole::Tadpole(const char *n) : Frog(n),age(0)
   {
   }
   
Bullfrog::Bullfrog(const char *n) : Frog(n)
   {
   }
   
void Tadpole::move()
   {
   age++;
   if ( age < 2 )
      cout << name << "Age " << age << " Swimming jerkily\n";
   else
      {
      cout << name <<" Age " << age <<
       " Swimming jerkily still, but changing into Bullfrog\n";
      Creature *f=Creature::newCreature(Bullfrog(name));
      Creature::altered = f;
      }
   }
   
Frog::~Frog() { }

// End of File