#ifndef SMARTPTR_H #define SMARTPTR_H /////////////////////////////////////////////////////////////// // smartPtr.h - pointer class that manages resources // // // // Jim Fawcett, CSE687 - Object Oriented Design, Spring 2005 // /////////////////////////////////////////////////////////////// // Boltins were described in detail in: // // "Imperfect C++", Matthew Wilson, Addison-Wesley, 2005 // /////////////////////////////////////////////////////////////// /* * Boltins are template classes that: * 1. derive publicaly from their first template parameter * 2. may add virtual methods or override base virtual methods * if the base class is polymorphic * 3. may increase the size of base by adding data members * and/or new virtual methods and/or new non-empty bases */ /////////////////////////////////////////////////////////////// // smartPtr - manages reference counted objects /////////////////////////////////////////////////////////////// // Answer begins here (member function bodies not required) template class smartPtr { public: smartPtr() : m_pTr(0) {} smartPtr(T* pT) : m_pTr(new T(*pT)) { m_pTr->addRef(); } smartPtr(const smartPtr& sp) : m_pTr(sp.m_pTr) { if(m_pTr) m_pTr->addRef(); } virtual ~smartPtr() { if(m_pTr) m_pTr->release(); } T& operator*() { return *m_pTr; } T* operator->() { return m_pTr; } template void set(U* pU = 0); smartPtr& operator=(const smartPtr& sp); protected: T* m_pTr; }; // answer ends here /////////////////////////////////////////////////////////////// // template template void smartPtr::set(U* pU = 0) { if(m_pTr) m_pTr->release(); if(pU) m_pTr = new U(*pU); else m_pTr = new U; m_pTr->addRef(); } template smartPtr& smartPtr::operator=(const smartPtr& sp) { if(this == &sp) return *this; if(m_pTr) m_pTr->release(); m_pTr = sp.m_pTr; m_pTr->addRef(); return *this; } // /////////////////////////////////////////////////////////////// // reference counted object boltin wrapper /////////////////////////////////////////////////////////////// // - adds reference counting to an object that // needs it so as to be smartPtr managed /////////////////////////////////////////////////////////////// template class refCounted : public T { public: refCounted() : m_count(0) {} refCounted(const T& t) : m_count(0), T(t) {} virtual ~refCounted() {} refCounted& operator=(const T& t) { static_cast(*this) = t; return *this; } void addRef() { ++m_count; } void release() { if(--m_count == 0) { delete this; #ifdef TEST_BOLTINS #include std::cout << "\n destroying ref counted object"; #endif } } protected: unsigned m_count; }; // /////////////////////////////////////////////////////////////// // reference counted object base /////////////////////////////////////////////////////////////// // - adds reference counting to an object that // needs it so as to be smartPtr managed /////////////////////////////////////////////////////////////// class irefCounted { public: irefCounted() : m_count(0) {} virtual ~irefCounted() {} void addRef() { ++m_count; } void release() { if(--m_count == 0) { delete this; #ifdef TEST_BOLTINS #include std::cout << "\n destroying ref counted object"; #endif } } protected: unsigned m_count; }; /////////////////////////////////////////////////////////////// // boltin wrapper for non-class types /////////////////////////////////////////////////////////////// // - makes a class that behaves like // an original primitive type /////////////////////////////////////////////////////////////// template class wrapped { public: wrapped() : m_T(0) {} wrapped(const wrapped& w) : m_T(w.m_T) {} wrapped(T t) : m_T(t) {} wrapped& operator=(T t) { m_T = t; } operator T () { return m_T; } private: T m_T; }; #endif