1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
template< typename T >
const Dam_ptr< T >& Dam_ptr< T >::operator= ( const Dam_ptr< T >& right ) // overloaded assignment operator
{
if ( this == &right )
return (*this);
if ( NULL != m_ptr ) // if m_ptr has a valid entry in AddressBook, decrement the count
{
AddressBook[m_pos].m_count--;
if ( 0 == AddressBook[m_pos].m_count ) // check if this is the last Dam_ptr pointing to the address
{
delete m_ptr;
}
}
m_pos = right.m_pos;
m_ptr = right.m_ptr;
if ( NULL != m_ptr )
{
AddressBook[m_pos].m_count++;
}
return (*this);
}
template< typename T >
const Dam_ptr< T >& Dam_ptr< T >::operator= ( T* const right ) // overloaded assignment operator so you can assign a pointer to a Dam_ptr
{
if ( m_ptr == right )
return (*this);
if ( NULL != m_ptr ) // if m_ptr has a valid entry in AddressBook, decrement the count
{
AddressBook[m_pos].m_count--;
if ( 0 == AddressBook[m_pos].m_count ) // check if this is the last Dam_ptr pointing to the address
{
delete m_ptr;
}
}
m_ptr = right;
if ( NULL == right )
{
m_pos = -1;
}
else // update AddressBook
{
int addr = (int)right;
m_pos = AddressBook.size (); // default the position is at the end, unless the address value is found somewhere in the vector
int count = getAddrCountAndIndex ( addr, m_pos );
if ( 0 == count )
{
AddressBook.push_back ( Mem_addr ( addr ) );
}
else
AddressBook[m_pos].m_count++;
}
return (*this);
}
template< typename T >
bool Dam_ptr< T >::operator== ( const Dam_ptr< T >& right ) const // overloaded equality operator. Left = Dam_ptr, Right = Dam_ptr
{
return ( ( this->m_ptr == right.m_ptr ) );
}
template< typename T >
bool Dam_ptr< T >::operator== ( const T* right ) const // overloaded equality operator. Left = Dam_ptr, Right = pointer to object of type T
{
return ( ( this->m_ptr == right ) );
}
template< typename T >
bool Dam_ptr< T >::operator!= ( const Dam_ptr< T >& right ) const // overloaded inequality operator. Left = Dam_ptr, Right = Dam_ptr
{
return ( ( this->m_ptr != right.m_ptr ) );
}
template< typename T >
bool Dam_ptr< T >::operator!= ( const T* right ) const // overloaded inequality operator. Left = Dam_ptr, Right = pointer to object of type T
{
return ( ( this->m_ptr != right ) );
}
template< typename T >
T* Dam_ptr< T >::getPtr () const // returns a copy of the pointer data member
{ return m_ptr; }
template< typename T >
int Dam_ptr< T >::getAddrCount ( int addr ) // static public member function to return how many Dam_ptrs are pointing to memory location addr
{
for ( int i = 0; i < AddressBook.size(); i++ )
{
if ( addr == AddressBook[i].m_addr )
return ( AddressBook[i].m_count );
}
return 0;
}
template< typename T >
int Dam_ptr< T >::getAddrCount ( T* ptr ) // static public member function to return how many Dam_ptrs are pointing to the object pointed to by ptr
{
return ( Dam_ptr< T >::getAddrCount ( (int)ptr ) );
}
template< typename T >
int Dam_ptr< T >::getAddrCountAndIndex ( int addr, int& index ) // static private member function to return how many Dam_ptrs are pointing to memory location addr, and also the index within AddressBook
{ // index is left unchanged if addr is not found within AddressBook
for ( int i = 0; i < AddressBook.size(); i++ )
{
if ( addr == AddressBook[i].m_addr )
{
index = i;
return ( AddressBook[i].m_count );
}
}
return 0;
}
|
So my code compiles just fine on Microsoft Visual Studio 2010 (but not on g++. I think the Microsoft compiler is smarter about type conversions). I can do things like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
// This block releases memory just fine
{
Dam_ptr < int > dptr = new int ( 10 );
int* ptr_to_int = new int ( 20 );
dptr = ptr_to_int;
}
// These conversions work fine
void f ( int* p )
{ /* implement f */ }
void g ( Dam_ptr< int > dp )
{ /* implement g */ }
f ( dptr ); // this call works because Dam_ptr<T> can conert implicitly to T*
g ( ptr_to_int ); // and vice versa
|
Here's what I can't get to work. For example, if I have a function f () that takes a Dam_ptr < double > as a parameter, I feel that I should be able to pass to f () a Dam_ptr < int > or even a int*, since if there is a finction g () that takes a double as an argument, then I can pass an int to the function and it'd work just fine.
So, how can I, without explicitly writing out every single possible conversion (theoretically infinite), let my Dam_ptr < SomeType> convert to Dam_ptr< RelatedType >, assuming that an implicit conversion can be done with the underlying types (like say...a Base Class and a Derived Class or a double and an int).
That is my main question. Secondary questions include: What other functionalities should this class logically provide? Are there any glaring design errors (aka is there anything I can do obviously better) in this class?
If this code is horribly mangled and makes you want to facepalm, then I apologize up front. I am no master of pointers and I am just beginning to learn templates and the issues they bring, so please bear with me. Thank you very much!