 // Purpose.  Visitor  ("recovering      // Discussion.  First we dispatch
 // lost type information" without       // based on the type of the Suspect.
 // type-querying and type-casting)      // Then the Suspect passes its
 //                                      // identity/type to the Visitor.  The
 // Discussion.  Suspects know if they   // compiler chooses which of Visitor's
 // are Innocent or Guilty.  Outsiders   // overloaded visit() methods to call
 // have to query their "type", and      // on the basis of the type of
 // once they have found the sorry       // Suspect, and immediately we know
 // miscreant, they have to cast the     // "who dunnit".
 // pointer in order to beat a
 // confession out of the predator.      #include <iostream.h>

 #include <iostream.h>                   class Innocent;  class Guilty;

 enum TheTruth { Alibi, NoMotive,        class Visitor {
    NoMeans, GuiltyAsSin };              public:
                                            void visit( Innocent* );
 class Suspect {                            void visit( Guilty* );
 public:                                 };
    Suspect( TheTruth _theTruth ) {
       theTruth_ = _theTruth;            class Suspect {
       id_ = total_++; }                 public:
    TheTruth getTheTruth() {                Suspect()    { id_ = total_++; }
       return theTruth_; }                  virtual void accept( Visitor ) = 0;
 protected:                              protected:
    int        id_;                         int        id_;
 private:                                   static int total_;
    TheTruth   theTruth_;                };
    static int total_;                   int Suspect::total_ = 0;
 };
 int Suspect::total_ = 0;                class Innocent : public Suspect {
                                         public:
 class Innocent : public Suspect {          void accept( Visitor gorilla ) {
 public:                                       gorilla.visit( this ); }
    Innocent( TheTruth tt )              };
       : Suspect( tt ) { }
 };                                      class Guilty : public Suspect {
                                         public:
 class Guilty : public Suspect {            void accept( Visitor gorilla ) {
 public:                                       gorilla.visit( this ); }
    Guilty()                                void confess() {
       : Suspect( GuiltyAsSin ) { }            cout << "Suspect " << id_ <<
    void confess() {                              ", \"I did it.\"" << endl; }
       cout << "Suspect " << id_ <<      };
          ", \"I did it.\"" << endl; }
 };                                      void Visitor::visit( Innocent* s ) { }
                                         void Visitor::visit( Guilty* s )   {
 void setupSuspects( Suspect* s[] ) {       s->confess(); }
    s[0] = new Innocent( Alibi );
    s[1] = new Guilty;                   void roundUpSuspects( Suspect* s[] ) {
    s[2] = new Innocent( NoMotive );        s[0] = new Innocent;
    s[3] = new Innocent( NoMeans ); }       s[1] = new Guilty;
                                            s[2] = new Innocent;
 main()                                     s[3] = new Innocent; }
 {
    Suspect*       suspects[4];          main()
    setupSuspects( suspects );           {
                                            Visitor   gorilla;
    for (int i=0; i < 4; i++)               Suspect*  suspects[4];
       if (suspects[i]->getTheTruth()       roundUpSuspects( suspects );
             == GuiltyAsSin)
          ((Guilty*) suspects[i])           for (int i=0; i < 4; i++)
             ->confess();                      suspects[i]->accept( gorilla );
 }                                       }

 // Suspect 1, "I did it."               // Suspect 1, "I did it."

