Dec 1, 2008 at 7:31pm UTC
#include <iostream>
using namespace std;
const int DefaultSize = 10;
class Animal
{
public:
Animal(int);
Animal();
~Animal(){}
int GetWeight() const {return itsWeight;}
void Display() const {std::cout << itsWeight;}
private:
int itsWeight;
};
Animal::Animal(int weight):itsWeight(weight)
{}
Animal::Animal():itsWeight(0)
{}
template <class T>
class Array
{
private:
T* pType;
int itsSize;
public:
Array(int itsSize = DefaultSize);
Array(const Array &rhs);
~Array(){delete [] pType;}
Array& operator=(const Array&);
T& operator[](int offset){ return pType[offset];}
const T& operator[](int offset) const
{ return pType[offset];}
int GetSize() const {return itsSize;}
};
template <class T>
Array<T>::Array(int size):itsSize(size)
{
pType = new T[size];
}
template <class T>
Array<T>::Array(const Array &rhs)
{
itsSize = rhs.GetSize();
pType = new T[itsSize];
for (int i=0; i<itsSize; i++)
{
pType[i] = rhs[i];
}
}
template<class T>
Array<T>& Array<T>::operator=(const Array &rhs)
{
if(this == &rhs)
{
return *this;
}
delete [] pType;
itsSize = rhs.GetSize();
pType = new T[itsSize];
for(int i=0; i<itsSize; i++)
{
pType[i] = rhs[i];
}
return *this;
}
int main()
{
Array<int> theArray;
Array<Animal> theZoo;
Animal *pAnimal;
for(int i=0; i<theArray.GetSize(); i++)
{
theArray[i] = i*2;
pAnimal = new Animal(i*3);
theZoo[i] = *pAnimal;
delete pAnimal;
}
for(int j=0; j<theArray.GetSize(); j++)
{
std::cout << "theArray[" << j << "]:\t";
std::cout << theArray[j] << "\t\t";
std::cout << "theZoo[" << j << "]:\t";
theZoo[j].Display();
std::cout << std::endl;
}
return 0;
}
This is a working program showcasing use of templates and operator overloading. In the main program, if line:
theZoo[i] = *pAnimal; is replaced by:
theZoo[i] = pAnimal;
and if an overloaded template function for operator = is added like this:
template<class T>
Array<T>& Array<T>::operator=(const Array* rhs)
{
if(this == &rhs)
{
return *this;
}
delete [] pType;
itsSize = (*rhs).GetSize();
pType = new T[itsSize];
for(int i=0; i<itsSize; i++)
{
pType[i] = *(rhs+i);
}
return *this;
}
Here the template takes pointer to Array as argument and accesses value at that pointer location to copy each element of array.
The program gives compilation error: binary '=' : no operator defined which takes a right-hand operand of type 'class Animal *' (or there is no acceptable conversion)
What I couldn't understand is this - if theZoo[i] = *pAnimal works fine along with its template function, why couldn't theZoo[i] = pAnimal work with its corresponding template function?
Any hints are appreciated. Thanks in advance.
Dec 1, 2008 at 8:03pm UTC
You would need to implement
operator=( const Animal* rhs );
on class Animal, because the expression "theZoo[x]" has type Animal, not Array.
Dec 2, 2008 at 3:37pm UTC
Thanks for the reply jsmith.
Can you please tell me how exactly to decide the class for operator=(), in both these cases?
1) theZoo[i] = *pAnimal - correct working is, it should be in template Array
2) theZoo[i] = pAnimal - you said it should be in class Animal
Thanks.
Dec 2, 2008 at 5:46pm UTC
What is the type of theZoo[i]? It is Animal, correct? (You've implemented operator[] on Array to return a T& where T=Animal).
Then Animal::operator=() is called with the rvalue as parameter. The rvalue in case #1 is *pAnimal which has type Animal. In case #2 it is Animal*.
In general, in the expression x = y where x has type X and y has type Y, X::operator=( const Y& ) is invoked.
Dec 3, 2008 at 3:46pm UTC
I tried the program and found that the second case will work if an array of pointer to Animal is declared like this:
Array<Animal*> theZoo;
So I think I have understood it now. Thanks a lot.