I am writing code for smart pointers as an exercise. Using tutorials online (1 , 2) I have developed a normal smart-pointer class with reference counting. The problem is I am unable to figure out the following:
when the smart pointer detects that no more references exist to a particular object, it must delete the object via a pointer to the original type, even if the template argument of the final smart pointer is of a base type. This is to avoid object slicing for non-virtual destructors.
How can I achieve that. Basically my code looks like below (from the tutorial).
template < typename T > class SP
{
private:
T* pData; // pointer
RC* reference; // Reference count
public:
SP() : pData(0), reference(0)
{
// Create a new reference
reference = new RC();
// Increment the reference count
reference->AddRef();
}
SP(T* pValue) : pData(pValue), reference(0)
{
// Create a new reference
reference = new RC();
// Increment the reference count
reference->AddRef();
}
SP(const SP<T>& sp) : pData(sp.pData), reference(sp.reference)
{
// Copy constructor
// Copy the data and reference pointer
// and increment the reference count
reference->AddRef();
}
~SP()
{
// Destructor
// Decrement the reference count
// if reference become zero delete the data
if(reference->Release() == 0)
{
delete pData;
delete reference;
}
}
T& operator* ()
{
return *pData;
}
T* operator-> ()
{
return pData;
}
SP<T>& operator = (const SP<T>& sp)
{
// Assignment operator
if (this != &sp) // Avoid self assignment
{
// Decrement the old reference count
// if reference become zero delete the old data
if(reference->Release() == 0)
{
delete pData;
delete reference;
}
// Copy the data and reference pointer
// and increment the reference count
pData = sp.pData;
reference = sp.reference;
reference->AddRef();
}
return *this;
}
};
EDIT:
To achieve that I have to have a pointer to the original type.
I have posted a question here: delete via a pointer to Derived, not Base
But Now since viewing the comments and answers I think both are related. I have the constructor:
template <typename T>
template <typename U>
Sptr<T>::Sptr(U* u) : obj(u),ref(NULL) {
//do something
ref = new RC();
ref->AddRef();
}
Now consider Sptr<Base1> sp(new Derived);
where Derived
is derived from Base1
. Base1 has protected constructor/destructor.
Which is storing for an object of type T
But I need to store it through an object of type U. I need to preserve that. How can I do that?