Panda3D
 All Classes Functions Variables Enumerations
pointerTo.h
00001 // Filename: pointerTo.h
00002 // Created by:  drose (23Oct98)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #ifndef POINTERTO_H
00016 #define POINTERTO_H
00017 
00018 ////////////////////////////////////////////////////////////////////
00019 //
00020 // This file defines the classes PointerTo and ConstPointerTo (and
00021 // their abbreviations, PT and CPT).  These should be used in place of
00022 // traditional C-style pointers wherever implicit reference counting
00023 // is desired.
00024 //
00025 // The syntax is:                     instead of:
00026 //
00027 //    PointerTo<MyClass> p;            MyClass *p;
00028 //    PT(MyClass) p;
00029 //
00030 //    ConstPointerTo<MyClass> p;       const MyClass *p;
00031 //    CPT(MyClass) p;
00032 //
00033 // PointerTo and ConstPointerTo will automatically increment the
00034 // object's reference count while the pointer is kept.  When the
00035 // PointerTo object is reassigned or goes out of scope, the reference
00036 // count is automatically decremented.  If the reference count reaches
00037 // zero, the object is freed.
00038 //
00039 // Note that const PointerTo<MyClass> is different from
00040 // ConstPointerTo<MyClass>.  A const PointerTo may not reassign its
00041 // pointer, but it may still modify the contents at that address.  On
00042 // the other hand, a ConstPointerTo may reassign its pointer at will,
00043 // but may not modify the contents.  It is like the difference between
00044 // (MyClass * const) and (const MyClass *).
00045 //
00046 // In order to use PointerTo, it is necessary that the thing pointed
00047 // to--MyClass in the above example--either inherits from
00048 // ReferenceCount, or is a proxy built with RefCountProxy or
00049 // RefCountObj (see referenceCount.h).  However, also see
00050 // PointerToArray, which does not have this restriction.
00051 //
00052 // It is crucial that the PointerTo object is only used to refer to
00053 // objects allocated from the free store, for which delete is a
00054 // sensible thing to do.  If you assign a PointerTo to an automatic
00055 // variable (allocated from the stack, for instance), bad things will
00056 // certainly happen when the reference count reaches zero and it tries
00057 // to delete it.
00058 //
00059 // It's also important to remember that, as always, a virtual
00060 // destructor is required if you plan to support polymorphism.  That
00061 // is, if you define a PointerTo to some base type, and assign to it
00062 // instances of a class derived from that base class, the base class
00063 // must have a virtual destructor in order to properly destruct the
00064 // derived object when it is deleted.
00065 //
00066 ////////////////////////////////////////////////////////////////////
00067 
00068 #include "pandabase.h"
00069 #include "pointerToBase.h"
00070 #include "register_type.h"
00071 
00072 ////////////////////////////////////////////////////////////////////
00073 //       Class : PointerTo
00074 // Description : PointerTo is a template class which implements a
00075 //               smart pointer to an object derived from
00076 //               ReferenceCount.
00077 ////////////////////////////////////////////////////////////////////
00078 template <class T>
00079 class PointerTo : public PointerToBase<T> {
00080 public:
00081   typedef TYPENAME PointerToBase<T>::To To;
00082 PUBLISHED:
00083   INLINE PointerTo(To *ptr = (To *)NULL);
00084   INLINE PointerTo(const PointerTo<T> &copy);
00085   INLINE ~PointerTo();
00086 
00087 public:
00088   INLINE To &operator *() const;
00089   INLINE To *operator -> () const;
00090   // MSVC.NET 2005 insists that we use T *, and not To *, here.
00091   INLINE operator T *() const;
00092 
00093 PUBLISHED:
00094   // When downcasting to a derived class from a PointerTo<BaseClass>,
00095   // C++ would normally require you to cast twice: once to an actual
00096   // BaseClass pointer, and then again to your desired pointer.  You
00097   // can use the handy function p() to avoid this first cast and make
00098   // your code look a bit cleaner.
00099 
00100   // e.g. instead of (MyType *)(BaseClass *)ptr, use (MyType *)ptr.p()
00101 
00102   // If your base class is a derivative of TypedObject, you might want
00103   // to use the DCAST macro defined in typedObject.h instead,
00104   // e.g. DCAST(MyType, ptr).  This provides a clean downcast that
00105   // doesn't require .p() or any double-casting, and it can be
00106   // run-time checked for correctness.
00107   INLINE To *p() const;
00108 
00109   INLINE PointerTo<T> &operator = (To *ptr);
00110   INLINE PointerTo<T> &operator = (const PointerTo<T> &copy);
00111 
00112   // These functions normally wouldn't need to be redefined here, but
00113   // we do so anyway just to help out interrogate (which doesn't seem
00114   // to want to automatically export the PointerToBase class).  When
00115   // this works again in interrogate, we can remove these.
00116   INLINE bool is_null() const { return PointerToBase<T>::is_null(); }
00117   INLINE void clear() { PointerToBase<T>::clear(); }
00118 };
00119 
00120 
00121 ////////////////////////////////////////////////////////////////////
00122 //       Class : ConstPointerTo
00123 // Description : A ConstPointerTo is similar to a PointerTo, except it
00124 //               keeps a const pointer to the thing.
00125 //
00126 //               (Actually, it keeps a non-const pointer, because it
00127 //               must be allowed to adjust the reference counts, and
00128 //               it must be able to delete it when the reference count
00129 //               goes to zero.  But it presents only a const pointer
00130 //               to the outside world.)
00131 //
00132 //               Notice that a PointerTo may be assigned to a
00133 //               ConstPointerTo, but a ConstPointerTo may not be
00134 //               assigned to a PointerTo.
00135 ////////////////////////////////////////////////////////////////////
00136 template <class T>
00137 class ConstPointerTo : public PointerToBase<T> {
00138 public:
00139   typedef TYPENAME PointerToBase<T>::To To;
00140 PUBLISHED:
00141   INLINE ConstPointerTo(const To *ptr = (const To *)NULL);
00142   INLINE ConstPointerTo(const PointerTo<T> &copy);
00143   INLINE ConstPointerTo(const ConstPointerTo<T> &copy);
00144   INLINE ~ConstPointerTo();
00145 
00146 public:
00147   INLINE const To &operator *() const;
00148   INLINE const To *operator -> () const;
00149   INLINE operator const T *() const;
00150 
00151 PUBLISHED:
00152   INLINE const To *p() const;
00153 
00154   INLINE ConstPointerTo<T> &operator = (const To *ptr);
00155   INLINE ConstPointerTo<T> &operator = (const PointerTo<T> &copy);
00156   INLINE ConstPointerTo<T> &operator = (const ConstPointerTo<T> &copy);
00157 
00158   // This functions normally wouldn't need to be redefined here, but
00159   // we do so anyway just to help out interrogate (which doesn't seem
00160   // to want to automatically export the PointerToBase class).  When
00161   // this works again in interrogate, we can remove this.
00162   INLINE void clear() { PointerToBase<T>::clear(); }
00163 };
00164 
00165 
00166 // Finally, we'll define a couple of handy abbreviations to save on
00167 // all that wasted typing time.
00168 
00169 #define PT(type) PointerTo< type >
00170 #define CPT(type) ConstPointerTo< type >
00171 
00172 // Now that we have defined PointerTo, we can define what it means to
00173 // take the TypeHandle of a PointerTo object.
00174 
00175 template<class T>
00176 INLINE TypeHandle _get_type_handle(const PointerTo<T> *) {
00177   return T::get_class_type();
00178 }
00179 
00180 template<class T>
00181 INLINE TypeHandle _get_type_handle(const ConstPointerTo<T> *) {
00182   return T::get_class_type();
00183 }
00184 
00185 
00186 #include "pointerTo.I"
00187 
00188 #endif
 All Classes Functions Variables Enumerations