Overloading
Note: In any assignment operator there are five
things you need to worry about. and they need to be performed in the following
order:
check for assignment to
self. If it is so, skip to step five.
delete/free memory
associated with the instance
allocate new
memory
make the copy
return *this (or this or
current instance)
In Vector
class…
Vector & Vector::operator = (const Vector &v)
{
// step 1
if (this == &v) // checks address of this instance
and passed &v
return *this;
// step 2
delete [] data;
len = v.len;
// step 3
data = new float[len];
// step 4
for (int i=0; i<len; i++)
data[i] = v.data[i];
// step 5
return *this;
}
notice
that from the second line of step 2 through the assignment loop of step 4 is
identical as the copy constructor.
The key
difference is that the copy constructor assumes uninitialized instance
whereas in the assignment operator, current instance is initialized because it
is the left-hand side of the argument.
Example:
String s1 = "Hello"
This is not
calling the assignment operator, it calls the constructor because s1 is not
initialized.
String s2 = s1;
This calls the
copy constructor because s2 is being created and not
initialized.
String s3;
s3
= s2;
First calls the
default constructor for the first line. Then calls the operator assignment
on the second line because it's already been initialized by the
constructor.
Point 1
Explained:
say for example
the following is set:
Vector v1(ar1,
3);
Vector & v4 = v1;
// any change to one will go to other too
Vector v5;
what if you say
v4 = v1 or v5 = v5 ? (assignment to
self)
Step through the
overloaded operator= starting with step 2.
omit step one for reason of
explanation
delete memory
allocate new
memory
copy?? Where can you
copy from. The memory is deleted.
To fix this you
need to check when you're assigning to self, do nothing. Hence, Step
1
Point 5
Explained:
recall what we
know about chaining…
s1=s2=s3=s4; // chaining always evaluates right to
left
this is the same
as:
(s1
= (s2 = (s3=s4)));
because of this,
we need the same in operator= overloading. so..
the return type is a re3ferancde to the same type.
Vector & Vector::operator = (const Vector &v)
this explains
the need to return a de-referenced this in step 5 above.
To
concatenate two vectors together:
Vector v5; // assume initialized and containing (6, 8, -9,
-1.2)
Vector v6; // assume initialized and containing (1, 2)
Vector v7;
v7
= v5+v6; // want v7 to contain (6, 8, -9, -1.2, 1, 2)
if v8 = v6; and
you want to code v8 = v8+4.0; and also v8 += 3.0; we need to overload the
+operator. This will be done in two
versions.
Version 1
(for v8 = v8 + 4.0)
Vector Vector::operator+ (float f)const
{
Vector result;
result.len = len +1;
result.data = new float[len+1];
for(int i=0; i<len; i++)
result.data[i] = data[i];
result.data[len] = f;
return result;
}
Version 2
(for v7 = v5 + v6)
Vector Vector::operator+ (float first, float second)const
{
Vector result;
result.len = first.len + second.len;
result.data = new float[result.len];
int i=0;
for(; i<first.len; i++)
result.data[i] =
first.data[i];
for(; i<result.len; i++)
result.data[i] =
second.data[i];
return result;
}
operator +=
(for v8 += 3.0)
This is changing
current instance and making DMA larger. You can't free up memory first.
You must copy over the data in v8 to a new pointer and then reallocate
memory for v8 and copy original data into new memory and now add the 3.0.
Then, and only then, free up original memory for v8 which was in the new
pointer.
Vector Vector::operator +=(Vector v)
{
// create temporary instance
Vector temp;
temp.len = len + v.len;
temp.data = new double[temp.len];
int i=0;
// make copy
for(; i<len; i++) // note empty first
space, i is already zero
temp.data[i] =
data[i];
// add the second vector
for(; i<temp.len; i++)
temp.data[i] =
v.data[i];
// re-allocate memory for original
delete [] data;
data = new double[temp.len];
// copy back into original
for(i=0; i<temp.len; i++)
data[i] =
temp.data[i];
len = temp.len;
return *this;
}
|