// Phones3.cpp - Example of inheritance with polymorphism, abstract classes.
// From an idea of Coplein's "Advanced C++ Styles and Idioms", 1992,
// page 93.  Note many details have been omitted for the sake of clarity.
//
// Written by Wayne Pollock, Tampa Florida USA, 2000.

class Telephone
{
public:
   Telephone ();
   virtual void ring ();
   virtual bool isOnHook ();
   virtual bool isTalking () = 0;  // A "pure virtual" function, so
                                   // class Telephone is now "abstract".
   virtual bool isDialing ();
   LineNumber get_extension ();
   virtual ~Telephone ();

protected:
   LineNumber extension;
};

//Note we can still define a Telephone::isTalking() function, and invoke it!
void Telephone::isTalking () { ... }

class POTSPhone : public Telephone  // POTS = Plain Old Telephone Service
{
public:
   void isTalking () { Telephone::isTalking(); }  // Must define this member.
   ~POTSPhone () { ... }
   ...      // The rest of this class is unchanged.
};

class ISDNPhone : public Telephone  // Integrated Services digital Network
{
   void isTalking () { Telephone::isTalking(); }  // Must define this member.
   ...      // The rest of this class is unchanged.
};

class OperatorPhone : public ISDNPhone   // Note: inherits from ISDNPhone.
{
   void isTalking () { Telephone::isTalking(); }  // Must define this member.
   void ring () { ... }
   ...      // The rest of this class is unchanged.
};

class PrincessPhone : public POTSPhone  // A kind of POTSPhone.
{
   void isTalking () { Telephone::isTalking(); }  // Must define this member.
   ...      // The rest of this class is unchanged.
};

void ring_phones ( Telephone* phone_list [] )
{
   for ( Telephone* p = phone_list; p; ++p )  // End of list marked with NULL
      p->ring();
}

int main ()
{
   Telephone* phone_array[10];
   int i = 0;
   phone_array[i++] = new POTSPhone( "5384" );
   phone_array[i++] = new ISDNPhone( "1050" );
   phone_array[i++] = new OperatorPhone( "0" );
   phone_array[i++] = new POTSPhone( "5385" );
   ...
   phone_array[i++] = NULL;
   ring_phones( phone_array );
   ...
   delete phone_array[0];  // Note correct destructor is called!
   ...
   return 0;
}
