/////////////////////////////////////////////////////////////////////////// // SmartPointers.cpp - Manage objects on heap, using Reference Counting // // ver 1.1 // // Language: Visual C++, ver 8.0 // // Platform: Dell Dimension 9150, Windows XP, SP2 // // Application: CSE687 - Object Oriented Design, Prototype // // Author: Jim Fawcett, Syracuse University, CST 2-187 // // (315) 443-3948, jfawcett@twcny.rr.com // /////////////////////////////////////////////////////////////////////////// #include #include #include #include "smartPointers.h" #define VERBOSE // should move this to property: C++ preprocs unsigned irefCounted::wrapperCount = 0; void irefCounted::announce(annType at) { #ifdef VERBOSE if(at==creating) std::cout << "\n create "; else if(at==releasing) std::cout << "\n release - "; else std::cout << "\n destroy - "; std::cout << "ref counted obj #" << myWrapperCount; std::cout << ", of type " << typeid(*this).name(); std::cout.flush(); #endif } #ifdef TEST_SMARTPOINTERS void title(const std::string& msg, char underline='-') { std::string temp("\n "); temp += msg + "\n "; temp += std::string(msg.size()+2, underline); std::cout << temp.c_str(); } /////////////////////////////////////////////////// // this global object causes newlines to be emitted // after destroying local objects and leaving main struct FinalNewLines { ~FinalNewLines() { std::cout << "\n\n"; } } global; /////////////////////////////////////////////////// // test structure struct Stuff { int x; double y; char z; }; /////////////////////////////////////////////////// // test classes for reference counting wrapper class iBase : public irefCounted { public: iBase() {} virtual ~iBase() {} virtual std::string say() { return "I'm an iBase type"; } }; class iDerived : public iBase { public: iDerived() {} virtual ~iDerived() {} virtual std::string say() { return "I'm an iDerived type"; } }; class wBase { public: wBase() {} virtual ~wBase() {} virtual std::string say() { return "I'm a CountedBase type"; } }; typedef refCounted CountedBase; class CountedDerived : public CountedBase { public: CountedDerived() {} virtual std::string say() { return "I'm a CountedDerived type"; } virtual ~CountedDerived() {} }; // /////////////////////////////////////////////////// // test stub void main() { title("Testing SmartPointer Class",'='); std::cout << std::endl; ///////////////////////////////////////////////// title("creating a smart pointer to iBase:"); ///////////////////////////////////////////////// smartPtr sPiB(new iBase); sPiB->announce(); std::cout << "\n " << sPiB->say(); smartPtr sPiD(new iDerived); sPiD->announce(); std::cout << "\n " << sPiD->say(); smartPtr sPiD2(new iDerived); sPiD2->announce(); std::cout << "\n " << sPiD2->say() << std::endl; CountedBase cba; cba.announce(); CountedBase cbb; cbb.announce(); CountedDerived cda; cda.announce(); CountedDerived cdb; cdb.announce(); std::cout << std::endl; ///////////////////////////////////////////////// title("creating a smart pointer to wrapped double:"); ///////////////////////////////////////////////// ///////////////////////////////////////////////// // Test reference counting wrapper typedef wrapped wDouble; typedef refCounted< wDouble > CountedDouble; smartPtr< CountedDouble > spDouble1(new CountedDouble(3.1415927)); std::cout << "\n value pointed to = " << *spDouble1 << std::endl; ///////////////////////////////////////////////// title("after copy construction of another smart pointer:"); ///////////////////////////////////////////////// smartPtr< refCounted< wDouble > > spDouble2 = spDouble1; std::cout << "\n value pointed to = " << *spDouble2 << std::endl; ///////////////////////////////////////////////// title("after changing value via the new pointer:"); ///////////////////////////////////////////////// *spDouble2 = -3.5; std::cout << "\n value pointed to = " << *spDouble2; std::cout << "\n value pointed to by the original pointer:"; std::cout << "\n value pointed to = " << *spDouble1 << std::endl; // ///////////////////////////////////////////////// title("creating a smart pointer to struct { int; double; char; } myStuff"); ///////////////////////////////////////////////// Stuff myStuff = { -2, 3.5, 'Z' }; smartPtr< refCounted > spS1(new refCounted(myStuff)); std::cout << "\n char selected from myStuff = " << spS1->z << std::endl; ///////////////////////////////////////////////// title("after assignment of old pointer to new pointer"); ///////////////////////////////////////////////// smartPtr < refCounted > spS2; spS2 = spS1; std::cout << "\n char selected from myStuff = " << spS2->z << std::endl; ///////////////////////////////////////////////// title("after changing value via the new pointer:"); ///////////////////////////////////////////////// spS2->z = 'a'; std::cout << "\n char selected from myStuff = " << spS2->z; std::cout << "\n value pointed to by the original pointer:"; std::cout << "\n char selected from myStuff = " << spS1->z << std::endl; ///////////////////////////////////////////////// title("Testing Polymorphic Operations with wrapper reference counting:"); ///////////////////////////////////////////////// // test polymorphic operation CountedBase cb; cb.announce(); smartPtr spBase1(new CountedBase(cb)); spBase1->announce(); std::cout << "\n " << spBase1->say().c_str(); smartPtr spBase2(new CountedDerived); spBase2->announce(); std::cout << "\n " << spBase2->say().c_str() << std::endl; ///////////////////////////////////////////////// title( "Testing copy & assignment Operations with wrapper reference counting:" ); ///////////////////////////////////////////////// // test copy construction std::cout << "\n copy constructing from a pointer to derived"; smartPtr spBase3 = spBase2; std::cout << "\n " << spBase2->say().c_str(); std::cout << std::endl; // test assignment std::cout << "\n assigning a pointer to base to a pointer to derived"; spBase3 = spBase1; std::cout << "\n " << spBase3->say().c_str(); std::cout << std::endl; // ///////////////////////////////////////////////// title("Testing Containment of Smart Pointers:"); ///////////////////////////////////////////////// { typedef std::vector< smartPtr > VecSmtPtr; VecSmtPtr vsp; smartPtr inVec1(new CountedBase); smartPtr inVec2(new CountedDerived); vsp.push_back(inVec1); vsp.push_back(inVec2); vsp.push_back(inVec2); VecSmtPtr::iterator it; for(it=vsp.begin(); it!=vsp.end(); ++it) std::cout << "\n " << (*it)->say().c_str(); std::cout << std::endl; } std::cout << "\n\n finished testing containment\n"; } #endif