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

main()
    {
    PMF_VV pf = &Creature::move;  // bound to a virtual
    Pond walden;
    Creature *p1 = new Creature(Creature::TADPOLE,"Wiggly");
    walden.insert(p1);
    Creature *p2 = new Creature(Creature::BULLFROG,"Croaker");
    walden.insert(p2);

    walden.activate( pf );  // Tell all creatures to move

    return 0;
    }

/---------------------------------------------------------
//  Frog.h
#ifndef FROG_H
#define FROG_H
#include <iostream.h>
#include <rw/gslist.h>

class Creature
    {
public:
    enum type{BULLFROG,TADPOLE};
    Creature(type,char *);
    virtual void move() { object->move(); }
protected:
    Creature() : object(0) {}// default invoked by derived
private:
    Creature *object;
    };

declare(GSlist,Creature)

class Frog : public Creature
    {
protected:
    char *name;
public:
    Frog(char *p="Noname Frog") : name(p) {}
    ~Frog(); 
    char *Name() { return name; }
    virtual void move() {} 
    };

class Tadpole : public Frog
    {
public:
    Tadpole(char *name) : Frog(name) {};
    void move(){cout << name << " Swimming jerkily\n";}
    };

class Bullfrog : public Frog
    {
public:
    Bullfrog(char *name) : Frog(name) {};
    void move() { cout << name << " - I'M JUMPING\n"; }
    };

class Pond
    {
    GSlist(Creature) list;  // singly linked creature list
public:
    void activate( void (Creature::*pf) () );
    void insert(Creature*);
    };

// this typedef must be after the class declarations
// it may be useful to simplify declarations in the users program.
// useful for pointing to move(void) 
typedef void (Creature::*PMF_VV)();   
#endif
//------------------------------------------------------------
// Frog.cpp
#include <stdlib.h>
#include <frog.h>

void Pond::insert(Creature *f)
    {
    list.insert(f);
    }

void Pond::activate( PMF_VV pmf_vv )
    {
    GSlistIterator(Creature) it(list);
    Creature *resident;
    while ( resident = it() )
	{
	(resident->*pmf_vv)();
	}
    }

Creature::Creature(Creature::type t,char *name)
    {
    if ( t == TADPOLE )
	object = new Tadpole(name);
    else if( t == BULLFROG)
	object = new Bullfrog(name);
    else
	{
	cerr << "Invalid type in Creature ctor/n";
	exit(2);
	}
    }

Frog::~Frog() {}


