Here is my problem : I created a generic wrapper class to handle memory management for some other classes I have where i have implemented a clone method which is supposed to clone the object by providing a new object (and new pointer to it) :
template <class T>
class Wrapper
{
public :
Wrapper() { DataPtr = 0; }
Wrapper(const T& inner)
{
if (DataPtr != 0)
DataPtr = inner.clone();
else
DataPtr = 0;
}
~Wrapper()
{
if (DataPtr != 0)
delete DataPtr;
}
Wrapper& operator=(Wrapper& original)
{
if (this != &original)
{
delete DataPtr;
DataPtr = DataPtr = 0 ? 0 : original.DataPtr->clone();
}
return *this;
}
T& operator*()
{
return *DataPtr;
}
T* operator->()
{
return DataPtr;
}
const T& operator*() const
{
return *DataPtr;
}
const T* operator->() const
{
return DataPtr;
}
private :
T* DataPtr;
};
Say I have a Class that uses in it's private attributes Wrapper < Class2 > Obj; which has a clone method :
my issue is that trying to call any member using the overloaded access operator -> gives me : Exception thrown at 0x00007FF6122D4102 in Training.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
And I don't understand why I don't have access since DataPtr is a member of the Wrapper Class
Both dereferencing the wrapper by doing (*Obj).SomeMethod() and using the -> operator by doing Obj->SomeMethod() give the same results.
CodePudding user response:
So the issue after all was that my operator=
overload had a problem: After deleting DataPtr
, I tried checking if DataPtr
was null while it didn't exist. What I should do, instead, is check if the DataPtr
of the object I want to assign (i.e. original) was null.
Below is the corrected code :
template <class T>
class Wrapper
{
public:
Wrapper() { DataPtr = 0; } // the default constructor which point to nothing
Wrapper(const T& inner) // constructor
{
DataPtr = inner.Clone();
}
~Wrapper()
{
delete DataPtr;
}
Wrapper(const Wrapper<T>& original) // copy constructor when pass in a Wrapper class
{
if (original.DataPtr != 0)
DataPtr = original.DataPtr->Clone();
else
DataPtr = 0;
}
// return by reference to avoid unnecessary copy
Wrapper& operator= (const Wrapper<T>& oringinal)// overloading "=" assignement operator
{
if (this != &oringinal)
{
if (DataPtr != 0)
{
delete DataPtr;
DataPtr = (oringinal.DataPtr != 0) ? oringinal.DataPtr.Clone() : 0;
}
}
return *this; // return what this point to
}
// two version of dereferencing operator *
// dereference both const and non-const objects
T& operator*() // overloading "*" to get object from pointer
{
return *DataPtr;
}
const T& operator*() const // return a const object
{
return *DataPtr;
}
// overloading "->" to access method within pointed object
const T* operator ->() const
{
return DataPtr;
}
T* operator ->()
{
return DataPtr;
}
private:
T* DataPtr;
};