Main BLOGGER
Google
WWW THIS BLOG
Sunday, February 20, 2005
 
A tutorial for smart pointer and operator overload


#include <iostream>
using namespace std;
class sp1
{
public:
int data;
sp1* operator ->() { return this;};
//overload "->" operator "." can not be overloaded
};


//a data object that can be reference to a user data object, and count the references
//to it, and increment and decrement the reference counter.
// this class is used internally by smart pointer class CPtr
template<typename T>
class CDataPacket
{
private:
int RefNum;
public:
T* pData;
CDataPacket();
~CDataPacket();
void DecRef();
void IncRef();
};

template<typename T>
void CDataPacket<T>::DecRef()
{
if (RefNum == 0) return;

RefNum--;
if (RefNum == 0)
delete this;
}

template<typename T>
void CDataPacket<T>::IncRef()
{
RefNum++;
}

template<typename T>
CDataPacket<T>::CDataPacket()
{
pData = NULL;
RefNum = 0;
}

template<typename T>
CDataPacket<T>::~CDataPacket()
{
delete pData;
}

//////////////////smart pointer////////////
template<typename T>
class CPtr
{
private:
CDataPacket<T> * Refs;
public:
~CPtr();
CPtr();
T* operator->();
T & operator*();
operator T*();
CPtr<T>& operator = ( T* p);
CPtr<T>& operator = ( CPtr<T>& p);
};


// scenario
// T* p = new <T>
// CPtr p_self = p;
//processing
// decrease the reference number on the DataPacket Refs if it exists
// if the reference number of Refs becomes zero, it will be garbage-collected
// create a new DataPacket with the value p
// increate the reference number on the new DataPacket
template<typename T>
CPtr<T>& CPtr<T>::operator= ( T* p)
{
cout<< "overload CPtr<T>& CPtr<T>::operator= ( T* p)" <<endl;
if (Refs) Refs->DecRef();
Refs = new CDataPacket<T>
Refs->pData = p;
Refs->IncRef();
return *this;
}

//scenario
// CPtr<T> p_self;
// CPtr<T> p;
// p_self = p;
//processing: the same as above
template<typename T>
CPtr<T>& CPtr<T>::operator= ( CPtr<T>& p)
{
cout<< "overload CPtr<T>& CPtr<T>::operator= ( CPtr<T>& p) " <<endl;
if ( Refs)
Refs->DecRef();
Refs = p.Refs;
Refs->IncRef();
return *this;
}

//scenario
// CPtr<T> p_self = new <T>
// delete p_self;
//processing: the same as above

template<typename T>
CPtr<T>::~CPtr()
{
Refs->DecRef();
}

//scenario
// CPtr<T> p_self = new <T>
//processing
// no DataPacket is assigned, so set it to NULL
template<typename T>
CPtr<T>::CPtr()
{
Refs = NULL;
}

//scenario
// CPtr<T> p_self = new <T>
// p_self->XXX
//processing
// return the pointer to actural data
template<typename T>
T* CPtr<T>::operator ->()
{
cout<< "overload T* CPtr<T>::operator ->()" <<endl;
return Refs->pData;
}

//scenario
// CPtr<T> p_self = new <T>
// (*p_self).XXX
//processing
// return the actural data
template<typename T>
T& CPtr<T>::operator *()
{
cout<< "overload T& CPtr<T>::operator *()" <<endl;
return *(Refs->pData);
}

// CPtr<T> p_self = new <T>
// p_self[0] = <T> a;
//processing
// return the pointer to actural data

template<typename T>
CPtr<T>::operator T*()
{
cout<< "overload CPtr<T>::operator T*()" <<endl;
return Refs->pData;

}

/////////////Testing Class///////////////
class test
{
private:
int data;

public:
test(int i){ data = i;};
~test(){ cout << " class #"<<data<<" destroyed."<< endl; };
void DoSomeThing(){ cout << " class #"<<data<<" doing something."<< endl; };
};

int main()
{
//test 1: sp1 overload ->
sp1 t;
cout << "input a number" <<endl;
cin >> t.data;
cout << t->data <<endl;

//test2: CPtr overload
CPtr<int> pii;
pii = new int[10]; //overload CPtr<T>& CPtr<T>::operator= ( T* p)
pii[0]=0; //overload CPtr<T>::operator T*()
pii[2]=10; //overload CPtr<T>::operator T*()
cout << pii[0] << endl; //overload CPtr<T>::operator T*()
cout << pii[2] << endl; //overload CPtr<T>::operator T*()

//test3: test class
CPtr<test> ts0,ts1,ts2;

ts0 = new test(0); // overload CPtr<T>& CPtr<T>::operator= ( T* p)
ts1 = new test(1); // overload CPtr<T>& CPtr<T>::operator= ( T* p)
ts2 = new test(2); // overload CPtr<T>& CPtr<T>::operator= ( T* p)

ts0->DoSomeThing(); // class #0 doing something. overload T* CPtr<T>::operator ->()
ts1->DoSomeThing(); // class #1 doing something.
ts2->DoSomeThing(); // class #2 doing something.

///////// ts0--->test(0)
///////// ts1--->test(1)
///////// ts2--->test(2)

ts0 = ts1; // class #0 destroyed.
///////// ts0--->test(1)
///////// ts1--->test(1)
///////// ts2--->test(2)
// test(0) is garbage-collected

ts1 = ts2; // overload CPtr<T>& CPtr<T>::operator= ( CPtr<T>& p)
///////// ts0--->test(1)
///////// ts1--->test(2)
///////// ts2--->test(2)

ts0->DoSomeThing(); // class #1 doing something.
ts1->DoSomeThing(); // class #2 doing something.
ts2->DoSomeThing(); // class #2 doing something.

ts1 = ts0;
///////// ts0--->test(1)
///////// ts1--->test(1)
///////// ts2--->test(2)
ts0->DoSomeThing(); //class #1 doing something.
ts1->DoSomeThing(); // class #1 doing something.
ts2->DoSomeThing(); // class #2 doing something.

(*ts0).DoSomeThing(); // class #1 doing something. overload T& CPtr<T>::operator *()
} // class #2 destroyed.class #1 destroyed.




<< Home

Powered by Blogger

Google
WWW THIS BLOG