Operator Overloading - II
Let us consider some special cases of operator
overloading
Overloading of subscript operator:
subscript
operator can be
overloaded to access the dynamically allocated array elements within an
object.
class Arr { int *arr; int size; public: int& operator [](int n) ; int operator[](int n) const; /****code *****/ }; int &Arr::operator [](int index) { return arr[index]; } int Arr::operator [](int index) const { return arr[index]; }
Const version of
operator
function is written so that constant objects can also access array
elements. Non-constant version is helpful in modifying the array
elements.
Make sure
that non-const
version of [] function returns a reference, so that you can assign
values using statement like
obj1[3]=99;
Increment and Decrement operator ++ and --:
++ and --
have prefix and
postfix versions for basic data types. a++ and ++a. So how do we
overload these operators with
two versions?
For
postfix versions of these
functions, we should use a dummy int parameter.
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 |
class Number { int num; public: Number & operator++();/*prefix version*/ Number operator++(int a);/*postfix version*/ /****code***/ }; Number & Number::operator++() { num++; return *this; } Number Number::operator++(int dummy) { Number temp = *this; num++; return temp; } int main() { Number obj(9); Number obj2(1000); obj2 = ++obj;/*calls prefix*/ obj = obj2++;/*calls postfix*/ } |
new operator:
New
operator takes size_t
parameter and returns a void pointer. The easy way of overloading new
operator would be
void *Number::operator new(size_t bytes) { char *ptr = ::new char[bytes];/*call global new operator*/ return (void*) ptr; }
Note
that compiler provided
new operator for classes will be sufficient in most situations.
You
need to overload new and delete operator, only if you want to use your
own block of memory for dynamic allocation.
Insertion and Extraction operators (<< and >>) :
These two
operators are used to
read and write objects from iostreams
and files.
These should be overloaded
as non-member functions because their first parameter will not be
the current class object. . >> must have istream object as first parameter
and << must have ostream
object as first parameter.
These two
functions must return reference to
iostream objects in order to use chaining in io operation. And it is
necessary to use second parameter also as reference parameter in
extraction operator as the function modifies object.
ostream & operator <<(ostream& out, Number & obj) { out<<obj.num; return out; } istream & operator >>(istream& in, Number & obj) { in>>obj.num; return in; }
Conversion Operators:
These are
used to convert
objects to basic data types. They are written without return type.
Instead, data type is the name of the operator.
class Number { int a; public: operator int()/*Converts Number object to int*/ { return a; } /****code*****/ };
Function call operator:
parantheses
- () can be
overloaded to create an object which behaves like a function. Such
objects are called function objects or functors.
class Cube { public: int operator ()(int n) { return n*n*n; } }; int main() { Cube cobj; int m = cobj(10);/*this cubes 10 and returns answer*/ }
Overloading of assignment operator:
Compiler
provides overloaded
assignment operator function for a class. But you have to write your
own assignment operator function if you need deep copy.
Assignment
operator function
looks almost like a copy constructor. You allocate memory and you copy
elements.
But before
that, you should release earlier memory allocated.
There is
one more problem
however. What if you use a statement which ultimately becomes self
assignment
ob1 = ob1;
In this
case, if you delete
memory, all hell breaks loose.
To avoid
this problem, check for self
assignment, then
delete memory, allocate new memory and copy elements.
A& A::operator =(A & obj1) { if(this !=&obj1)/*self assignment?*/ { delete arr; arr = new int[obj1.n]; for(int i=0;i<n;i++) arr[i] = obj1.arr[i]; } return *this; }
Comments
Post a Comment