//smart4.cpp
#include <iostream.h>

template <class T> class Ptr;
class Seat	{
public:
   Seat() : ref(0){ cout << "Seat::Seat(), this=" << this << endl;	}
   ~Seat() { cout << "Seat::~Seat(), this=" << this << endl;	}
   void debug()	{ cout << "Seat(" << this << "), ref=" << ref << endl;	}
protected:
   int ref;
   friend class Ptr<Seat>;
   };

template <class T>
class Ptr	{
public:
   Ptr() : object(0) { }
   Ptr(T* o) : object(o) { object->ref += 1; }
   Ptr(const Ptr<T>& s) : object(s.object) { object->ref += 1;	}
   ~Ptr() { if ((object) && (--object->ref == 0)) delete object; }
   Ptr<T>& operator=(T* o)	{
	if ((object) && (--object->ref == 0)) delete object;
	object = o;	object->ref += 1;
	return *this;
   }
   T* operator->() { return object; }
protected:
   T* object;
};

typedef Ptr<Seat> SeatPtr;
class Airplane	{
public:
   Airplane() {	for(int i=0; i<3; i++) Seats[i] = new Seat; }
   SeatPtr getSeat(int seatNo) { return Seats[seatNo]; }
protected:
   SeatPtr Seats[3];
};
class Reservationist	{
public:
   Reservationist(Airplane &ap) : aSeat(ap.getSeat(1)) {}
protected:
   SeatPtr aSeat;
};
void main()	{
   Airplane *ap = new Airplane;
   SeatPtr seat = ap->getSeat(1); seat->debug();
   Reservationist *reservationist = new Reservationist(*ap);  seat->debug();
   delete reservationist;	  seat->debug();
   delete ap;			  seat->debug();
}
/***********output**********
Seat::Seat(), this=0x45f7041e
Seat::Seat(), this=0x480f0826
Seat::Seat(), this=0x480f081e
Seat(0x480f0826), ref=2
Seat(0x480f0826), ref=3
Seat(0x480f0826), ref=2
Seat::Seat(), this=0x480f081e
Seat::Seat(), this=0x45f7041e
Seat(0x480f0826), ref=1
Seat::Seat(), this=0x480f0826
*****************************/


