Professional C__ - Marc Gregoire [379]
class SuperSmartPointer
{
public:
explicit SuperSmartPointer(T* inPtr);
virtual ~SuperSmartPointer();
SuperSmartPointer(const SuperSmartPointer SuperSmartPointer const T& operator*() const; const T* operator->() const; T& operator*(); T* operator->(); operator void*() const { return mPtr; } protected: T* mPtr; static std::map void finalizePointer(); void initPointer(T* inPtr); }; template std::map template SuperSmartPointer { initPointer(inPtr); } template SuperSmartPointer { initPointer(src.mPtr); } template SuperSmartPointer SuperSmartPointer { if (this == &rhs) { return *this; } finalizePointer(); initPointer(rhs.mPtr); return *this; } template SuperSmartPointer { finalizePointer(); } template void SuperSmartPointer { mPtr = inPtr; if (sRefCountMap.find(mPtr) == sRefCountMap.end()) { sRefCountMap[mPtr] = 1; } else { sRefCountMap[mPtr]++; } } template void SuperSmartPointer { if (sRefCountMap.find(mPtr) == sRefCountMap.end()) { throw std::runtime_error("ERROR: Missing entry in map!"); } sRefCountMap[mPtr]--; if (sRefCountMap[mPtr] == 0) { // No more references to this object--delete it and remove from map sRefCountMap.erase(mPtr); delete mPtr; mPtr = nullptr; } } template const T* SuperSmartPointer { return mPtr; } template const T& SuperSmartPointer { return *mPtr; } template T* SuperSmartPointer { return mPtr; } template T& SuperSmartPointer { return *mPtr; } Code snippet from SuperSmartPointer\SuperSmartPointer.cpp Unit Testing the SuperSmartPointer The Nothing class defined earlier can be employed for a simple unit test for SuperSmartPointer. One modification is needed to determine if the test passed or failed. Two static members are added to the Nothing class, which track the number of allocations and the number of deletions. The constructor and destructor modify these values instead of printing a message. If the SuperSmartPointer works, the numbers should always be equivalent when the program terminates. Here is the adapted Nothing class: class Nothing { public: Nothing() { sNumAllocations++; } virtual ~Nothing() { sNumDeletions++; } static int sNumAllocations; static int sNumDeletions; }; int Nothing::sNumAllocations = 0; int Nothing::sNumDeletions = 0; Code snippet from SuperSmartPointer\SuperSmartPointer.cpp Following is the actual test. Note that an extra set of curly braces is used to keep the SuperSmartPointers in a smaller scope, so the example can show automatic allocation and deallocation self-contained within one block: Nothing* myNothing = new Nothing(); { SuperSmartPointer SuperSmartPointer } if (Nothing::sNumAllocations != Nothing::sNumDeletions) { std::cout << "TEST FAILED: " << Nothing::sNumAllocations << " allocations and " << Nothing::sNumDeletions << " deletions" << std::endl; } else { std::cout << "TEST PASSED" << std::endl; } Code snippet from SuperSmartPointer\SuperSmartPointer.cpp A successful execution of this test program will result in the following output: TEST PASSED You should also write additional tests for the SuperSmartPointer class. For example, you should test the copy construction and operator= functionality. This is left as an exercise for the reader. Enhancing This Implementation The previous SuperSmartPointer implementation is not completely free of problems. Templates exist on a per-type basis. In other words, if you have some SuperSmartPointers that store