I noticed that the code that accompanies the book states that the SmartPtr implementation used in the book's code is not polymorphic. That's a real drag since polymorphism IMHO is a trait that all SmartPtr implementations should support.
Anyway here's my SmartPtr implementation. It is modelled on the SmartPtr implementation from the book. It supports polymorphism, intrusive and non-intrusive reference counting, and correctly handles const pointer types. One thing that it doesn't currently do is correctly delete the pointer if it is an array. However this can be easily fixed by adding a Deletion policy to the SmartPtr.
One final note: the code uses member templates so you'll need at least VC 7 to compile the code.
Display All
Here's a little test application that should hopefully illustrate how to use my SmartPtr implementation. Notice that you shouldn't use RefCountedAdapter at all in your code - this class is used internally by the SmartPtr class for those pointer types that do not inherit from the RefCounted base class.
Display All
Anyway here's my SmartPtr implementation. It is modelled on the SmartPtr implementation from the book. It supports polymorphism, intrusive and non-intrusive reference counting, and correctly handles const pointer types. One thing that it doesn't currently do is correctly delete the pointer if it is an array. However this can be easily fixed by adding a Deletion policy to the SmartPtr.
One final note: the code uses member templates so you'll need at least VC 7 to compile the code.
Brainfuck Source Code
- //------------------------------------------------------------------------
- // $Id: smartptr.h,v 1.10 2003/11/16 07:06:48 dpoon Exp $
- //
- // Copyright (c) 2003 David Poon
- //
- // Permission is hereby granted, free of charge, to any person
- // obtaining a copy of this software and associated documentation
- // files (the "Software"), to deal in the Software without
- // restriction, including without limitation the rights to use,
- // copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom
- // the Software is furnished to do so, subject to the following
- // conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- // OTHER DEALINGS IN THE SOFTWARE.
- //------------------------------------------------------------------------
- #if !defined(SMARTPTR_H)
- #define SMARTPTR_H
- class RefCounted
- {
- public:
- RefCounted() : m_refCount(0)
- {
- }
- virtual ~RefCounted()
- {
- }
- int addRef()
- {
- return ++m_refCount;
- }
- int release()
- {
- int refCount = --m_refCount;
- if (refCount <= 0)
- delete this;
- return refCount;
- }
- int getRefCount() const
- {
- return m_refCount;
- }
- template <typename T>
- T *getPtr() const
- {
- return (T*)this;
- }
- private:
- int m_refCount;
- };
- //------------------------------------------------------------------------
- template <typename T>
- class RefCountedAdapter : public RefCounted
- {
- public:
- RefCountedAdapter(T *rhs) : m_pPointee(rhs)
- {
- }
- ~RefCountedAdapter()
- {
- if (getRefCount() <= 0)
- delete m_pPointee;
- }
- template <typename U>
- T *getPtr() const
- {
- return m_pPointee;
- }
- private:
- T *m_pPointee;
- };
- //------------------------------------------------------------------------
- class SmartPtrBase
- {
- public:
- SmartPtrBase() : m_pRefCounted(0)
- {
- }
- ~SmartPtrBase()
- {
- if (m_pRefCounted)
- m_pRefCounted->release();
- }
- RefCounted *getPtr() const
- {
- return m_pRefCounted;
- }
- protected:
- RefCounted *m_pRefCounted;
- };
- //------------------------------------------------------------------------
- template <typename T>
- class SmartPtr : public SmartPtrBase
- {
- public:
- SmartPtr()
- {
- }
- SmartPtr(SmartPtr<T> &rhs)
- {
- assign(rhs);
- }
- SmartPtr(RefCounted *rhs)
- {
- assign(rhs);
- }
- SmartPtr(SmartPtrBase &rhs)
- {
- assign(rhs);
- }
- SmartPtr(T *rhs)
- {
- assign(rhs);
- }
- SmartPtr &operator=(SmartPtr<T> &rhs)
- {
- if (!m_pRefCounted)
- {
- assign(rhs);
- }
- else
- {
- if (m_pRefCounted->getPtr<T>() != rhs.m_pRefCounted->getPtr<T>())
- assign(rhs);
- }
- return *this;
- }
- SmartPtr &operator=(RefCounted *rhs)
- {
- if (!m_pRefCounted)
- {
- assign(rhs);
- }
- else
- {
- if (m_pRefCounted->getPtr<T>() != rhs->getPtr<T>())
- assign(rhs);
- }
- return *this;
- }
- SmartPtr &operator=(SmartPtrBase &rhs)
- {
- if (!m_pRefCounted)
- {
- assign(rhs);
- }
- else
- {
- if (m_pRefCounted->getPtr<T>() != rhs.getPtr()->getPtr<T>())
- assign(rhs);
- }
- return *this;
- }
- SmartPtr &operator=(T *rhs)
- {
- if (!m_pRefCounted)
- {
- assign(rhs);
- }
- else
- {
- if (m_pRefCounted->getPtr<T>() != rhs)
- assign(rhs);
- }
- return *this;
- }
- template <typename U>
- operator SmartPtr<U>()
- {
- return SmartPtr<U>(m_pRefCounted);
- }
- ~SmartPtr()
- {
- }
- T *operator->() const
- {
- return m_pRefCounted->getPtr<T>();
- }
- T &operator*() const
- {
- return *m_pRefCounted->getPtr<T>();
- }
- bool operator!() const
- {
- return m_pRefCounted->getPtr<T>() == 0;
- }
- bool operator==(SmartPtrBase &rhs) const
- {
- return m_pRefCounted->getPtr<T>() == rhs.getPtr()->getPtr<T>();
- }
- bool operator!=(SmartPtrBase &rhs) const
- {
- return m_pRefCounted->getPtr<T>() != rhs.getPtr()->getPtr<T>();
- }
- private:
- void assign(SmartPtr<T> &rhs)
- {
- if (m_pRefCounted)
- m_pRefCounted->release();
- m_pRefCounted = rhs.m_pRefCounted;
- if (m_pRefCounted)
- m_pRefCounted->addRef();
- }
- void assign(RefCounted *rhs)
- {
- if (m_pRefCounted)
- m_pRefCounted->release();
- m_pRefCounted = rhs;
- if (m_pRefCounted)
- m_pRefCounted->addRef();
- }
- void assign(SmartPtrBase &rhs)
- {
- if (m_pRefCounted)
- m_pRefCounted->release();
- m_pRefCounted = rhs.getPtr();
- if (m_pRefCounted)
- m_pRefCounted->addRef();
- }
- void assign(T *rhs)
- {
- if (m_pRefCounted)
- m_pRefCounted->release();
- if (rhs != 0)
- {
- m_pRefCounted = new RefCountedAdapter<T>(rhs);
- m_pRefCounted->addRef();
- }
- }
- };
- #endif
Here's a little test application that should hopefully illustrate how to use my SmartPtr implementation. Notice that you shouldn't use RefCountedAdapter at all in your code - this class is used internally by the SmartPtr class for those pointer types that do not inherit from the RefCounted base class.
C Source Code
- #if defined(_DEBUG)
- # define CRTDBG_MAP_ALLOC
- # include <crtdbg.h>
- #endif
- #include <iostream>
- #include "smartptr.h"
- class Base : public RefCounted
- {
- public:
- Base()
- {
- std::cout << "Base::Base()" << std::endl;
- }
- ~Base()
- {
- std::cout << "Base::~Base()" << std::endl;
- }
- void message() const
- {
- std::cout << "Base::message()" << std::endl;
- }
- };
- class Derived : public Base
- {
- public:
- Derived()
- {
- std::cout << "Derived::Derived()" << std::endl;
- }
- ~Derived()
- {
- std::cout << "Derived::~Derived()" << std::endl;
- }
- };
- void TestSmartPtr()
- {
- SmartPtr<Derived> pDerived;
- SmartPtr<const Base> pBase;
- pDerived = new Derived;
- pBase = pDerived;
- if (!pDerived)
- {
- std::cout << "SmartPtr<Derived> is NULL" << std::endl;
- }
- else
- {
- pDerived->message();
- (*pDerived).message();
- if (pDerived != pBase)
- std::cout << "SmartPtr<Derived> != SmartPtr<Base>" << std::endl;
- if (!(pDerived == pBase))
- std::cout << "SmartPtr<Derived> != SmartPtr<Base>" << std::endl;
- }
- }
- int main()
- {
- #if defined(_DEBUG)
- _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF);
- #endif
- TestSmartPtr();
- std::cout << "Press enter to continue...";
- std::cin.get();
- return 0;
- }
The post was edited 2 times, last by dpoon ().