home *** CD-ROM | disk | FTP | other *** search
/ AI Game Programming Wisdom / AIGameProgrammingWisdom.iso / SourceCode / 10 Scripting / 02 Berger / scc / SmartPtr.H < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-14  |  5.1 KB  |  150 lines

  1. #ifndef __SmartPtr_H__
  2. #define __SmartPtr_H__
  3.  
  4.  
  5. // Define an intrusive reference counting base class.  The SmartPtr class
  6. // expects that its type is derived from this class.  This class handles all
  7. // the details of keeping the reference variable, and it will delete itself
  8. // when the reference count reaches zero.
  9. class RefCount {
  10. public:
  11.   // Define the class's default constructor & destructor.  Note that the
  12.   // destructor must be virtual since this class will actually "delete this".
  13.   // If the destructor isn't virtual, then the derived class's destructor
  14.   // won't be called.
  15.   RefCount();
  16.   virtual ~RefCount();
  17.  
  18.  
  19.   // These two api functions increment and decrement the reference count for
  20.   // this class.  When the reference count is decremented to zero, this object
  21.   // will delete itself.  The SmartPtr class will call these two functions
  22.   // automatically.
  23.   void AddReference();
  24.   void RemoveReference();
  25.  
  26.  
  27. private:
  28.   // This data member keeps track of the number of references currently active.
  29.   unsigned int m_refs;
  30. };
  31.  
  32.  
  33.  
  34. // Define a smart pointer template.  This smart pointer is reference counded,
  35. // so the allocated memory does not have to manually deleted.  This is very
  36. // handy for Bison since it's common to toss pointers around a lot in complex
  37. // grammars.  Note that this smart pointer requires that the class be derived
  38. // from RefCount.
  39. template <class T>
  40. class SmartPtr {
  41. public:
  42.   // This is the default constructor and the constructor that can be used to
  43.   // create a smart pointer to a specific pointer.  The smart pointer will
  44.   // point to the given pointer, and it will increment the reference count of
  45.   // the object.
  46.   SmartPtr( T *ptr = NULL )
  47.     : m_ptr( NULL )
  48.   {
  49.     SetPtr( ptr );
  50.   }
  51.  
  52.   // This constructor allows one smart pointer to be created from an other
  53.   // smart pointer type.  This is useful in up/down casting a pointer through
  54.   // the inheritance tree.  Since static_cast is used to do the actual pointer
  55.   // conversion, compile errors will still be thrown if the two smart pointers
  56.   // are not compatiable.
  57.   //
  58.   // Note that this constructor is explicit.  This helps the developer to not
  59.   // accidently cast a smart poitner from one type to another type.
  60.   template <class Y> explicit SmartPtr( const SmartPtr<Y>& s )
  61.     : m_ptr( NULL )
  62.   {
  63.     SetPtr( static_cast<T *>( s.GetPtr() ) );
  64.   }
  65.  
  66.   // This is the copy constructor.  This smart pointer will initialize itself
  67.   // to the given smart pointer, and it will also properly increment the
  68.   // object's reference counter.
  69.   SmartPtr( const SmartPtr& s )
  70.     : m_ptr( NULL )
  71.   {
  72.     SetPtr( s.GetPtr() );
  73.   }
  74.  
  75.   // This is the destructor for the smart pointer.  This function sets the
  76.   // internal pointer to NULL.  This will handle decrementing the reference
  77.   // counter and maybe deleting the object that this smart pointer points to.
  78.   ~SmartPtr()
  79.   {
  80.     SetPtr( NULL );
  81.   }
  82.  
  83.   // The smart pointer needs to override the default assignment operator to
  84.   // make sure that the reference counting is properly handled.
  85.   SmartPtr& operator=( const SmartPtr& rhs )
  86.   {
  87.     SetPtr( rhs.GetPtr() );
  88.     return *this;
  89.   }
  90.  
  91.   // This is just like the default assignment operator; however, this
  92.   // operator= expects that the given type is the same pointer type.  This is
  93.   // the most common way of changing what a smart pointer points to.
  94.   SmartPtr& operator=( T *rhs )
  95.   {
  96.     SetPtr( rhs );
  97.     return *this;
  98.   }
  99.  
  100.   // Provide some equality operators that allow testing if this smart pointer
  101.   // is equivalent to some other pointer.
  102.   bool operator==( T *rhs ) const      { return m_ptr == rhs; }
  103.   bool operator!=( T *rhs ) const      { return m_ptr != rhs; }
  104.  
  105.   // This function returns the true pointer that this smart pointer refers
  106.   // to.  This is mainly useful internally, but it might be useful external
  107.   // source code if you don't want to call the T* typecast operator.
  108.   T* GetPtr() const   { return m_ptr;  }
  109.  
  110.   // These next three functions define the various operators that are needed
  111.   // by a smart pointer to act & feel like a normal pointer.
  112.   operator T*()       { return m_ptr;  }
  113.   T& operator*()      { return *m_ptr; }
  114.   T* operator->()     { return m_ptr;  }
  115.  
  116.  
  117. private:
  118.   // This function handles the details of changing the internal pointer.  It
  119.   // will handle incrementing and decrementing the object's reference as
  120.   // needed.
  121.   void SetPtr( T *ptr );
  122.  
  123.   // This pointer points to the true object for this smart pointer.
  124.   T *m_ptr;
  125. };
  126.  
  127.  
  128.  
  129.  
  130. template <class T>
  131. void
  132. SmartPtr<T>::SetPtr( T *ptr )
  133. {
  134.   // Before we can change the internal pointer data member, it is important to
  135.   // decrement the reference count on our existing object.
  136.   if ( m_ptr != NULL )
  137.     m_ptr->RemoveReference();
  138.  
  139.   // Set our pointer data member to refer to this new object.
  140.   m_ptr = ptr;
  141.  
  142.   // Now that we have control over this new object, make sure to increment the
  143.   // reference counter for the new object.
  144.   if ( m_ptr != NULL )
  145.     m_ptr->AddReference();
  146. }
  147.  
  148.  
  149. #endif // __SmartPtr_H__
  150.