RefPtr and RefPtrConst

[C++]

template <class T>
class RefPtrConst : public RefData<T>
{
public:
  RefPtrConst() {}
  RefPtrConst(T const* ptr);           // AddRef() called
  RefPtrConst(RefPtrConst<..> refPtr); // AddRef() called
  ~RefPtrConst();                      // Release() called
  
  // Copy operator
  RefPtrConst<T>& operator= (T const* ptr);            // AddRef() called
  RefPtrConst<T>& operator= (RefPtrConst<..> refPtr);  // AddRef() called
  
  void Reset();                 // Release() called; the wrapped object is detached
  
  // Accessors
  T const* Get() const;
  T const* operator-> () const;
  T const& GetRef() const;
}


template <class T>
class RefPtr : public RefPtrConst<T>
{
public:
  RefPtr() {}
  RefPtr(T const* ptr);      // AddRef() called
  RefPtr(RefPtr<..> refPtr); // AddRef() called
  
  // Copy operator
  RefPtr<T>& operator= (T const* ptr);       // AddRef() called
  RefPtr<T>& operator= (RefPtr<..> refPtr);  // AddRef() called
  
  // Accessors
  T const* Get() const;
  T const* operator-> () const;
  T const& GetRef() const;
}

Remarks

RefCountable. In FlowSshCpp, all objects derived from RefCountable are reference counted objects. The following rules outline usage guidelines for them:

  1. Always create them on the heap (dynamic allocation).
  2. Never delete them. They provide AddRef and Release calls similar to those found in COM objects. FlowSshCpp will automatically destroy these objects after their reference count drops to 0.
    Important: These objects are destroyed when both the user AND the FlowSshCpp library have released them. When the user releases an object before the library does, the object will continue to exist until it is released by the library. During this time, its handlers may still be called.
  3. Use our convenient RefPtr. Example:
        RefPtr<Client> client(new Client);
    RefPtr manages the necessary AddRef and Release calls of the wrapped object. On occasions where you cannot use RefPtr, be sure to call AddRef and Release as appropriate.

RefPtr and RefPtrConst. Declarations at the beginning of this document show that RefPtr and RefPtrConst are related and provide nearly identical functionality; the difference between them is that RefPtrConst only permits non-mutable access to the object.

When a pointer to a RefCountable object is assigned to a RefPtr or RefPtrConst, AddRef is called. When RefPtr or RefPtrConst is destroyed, or changed to point to a different object, Release is called on the original RefCountable object. The final Release deletes the object.

function Example()
{
  Client* rawPtr = new Client();     // RefCount=INIT_REFCOUNT

  RefPtr<Client> refPtr1(rawPtr);    // RefCount=1
  RefPtr<Client> refPtr2 = refPtr1;  // RefCount=2
}

As the function goes out of scope first refPtr2 is destroyed; the destructor of refPtr2 calls Release on the Client object, dropping its reference count to 1. Then refPtr1 is destroyed; at this point the reference count of the Client object reaches zero, and the object is destroyed.

Accessors. There are several accessors available for RefPtr and RefPtrConst. Get returns a raw pointer and GetRef a reference to the wrapped object. Though, most of the times you will simply use the operator->. It lets you access the wrapped object as if using an ordinary raw pointer.

function Accessors()
{
  RefPtr<Client> refPtr(new Client());

  Client* rawPtr = refPtr.Get();
  Client& refrnc = refPtr.GetRef();
  
  refPtr->SetUserName(L"myname"); // operator-> is used
}