• No results found

Operator overloading Consider the following class,

In document (OOP)_01-45(22-08-2009) updated.doc (Page 139-147)

chairs[50]:Chair *Room

16.1. Operator overloading Consider the following class,

class Complex{

private:

double real, img;

public:

Complex Add(const Complex &);

Complex Subtract(const Complex &);

Complex Multiply(const Complex &);

}

We want to write function to add two complex no. objects, the Add

function implementation to add two complex numbers is shown below, this function is taking one complex no object and its adding the current (with reference to which it will be called) and is returning result in new object, Complex Complex::Add(

const Complex & c1){

Complex t;

t.real = real + c1.real;

t.img = img + c1.img;

return t;

}

// adds the contents of c2 to c1

// creating new object c3 and assigning it result of c1+c2

Now we can add two complex no. objects using the following statement, Complex c3 = c1.Add(c2);

In this statement two operations are taking place,

1. One is addition of two objects using the function call Add and returning the result in a new object.

Complex c3 = c1.Add(c2);

2. Second is copy of that temporary object to newly created object c3 using copy constructor.

Complex c3 = c1.Add(c2);

Complex c3 = c1 + c2; // error Instead we have to explicitly write, Complex c3 = c1.Add(c2)

If we give our complex no. class code some user in compiled form for use, user will need to know how we have written Add function (no. of parameters , return type) to add two complex no. objects so that he can call Add function correctly.

2. If we want to perform add operation on more than two objects in a single mathematical statement like:

c1+c2+c3+c4

We are unable to do it.

We have to explicitly write, c1.Add(c2.Add(c3.Add(c4))) Alternative way is:

t1 = c3.Add(c4);

t2 = c2.Add(t1);

t3 = c1.Add(t2);

This is also overhead, especially if the mathematical expression is large, Converting it to C++ code will involve complicated mixture of function calls

Code will become less readable

Chances of human mistakes will become very high Code produced will be very hard to maintain

The solution to this problem is simple that we can write normal operators like +,-,*, and so on for our user defined classes as well,

It is “Operator overloading”

Using operator overloading we can perform basic operations (like addition, subtraction, multiplication, division and so on…) on our own defined classes objects in the similar way as we perform them on basic built-in types(like int, float, long, double etc.).

C++ allows us to overload common operators like +, - or * etc…

With operator overloading Mathematical statements don’t have to be explicitly converted into function calls as we had to do to add two complex

The resultant code is very easy to read, write and maintain Operator overloading

C++ automatically overloads operators for pre-defined types as these have also been implemented as classes by c++.

Example of predefined types:

int float double char long

Operator overloading float x;

int y;

x = 102.02 + 0.09; // overloaded operator ‘+’ for float type will be called by c++

Y = 50 + 47; // overloaded operator ‘+’ for int type will be called by c++

The compiler probably calls the correct overloaded low level function for addition i.e:

// for integer addition:

Add(int a, int b) // for float addition:

Add(float a, float b) Operator overloading

Operator functions are not usually called directly, they are automatically invoked to evaluate the operations they implement by compiler.

List of operators that can be overloaded in C++:

argument as you have seen previously in the use of dot (‘.’) operator, Student std;

int roll = std.getRollNo() // dot operator is performing on actual function (getRollNo) of class Student that will vary from program to program.

?: is the only ternary operator in C++ and can’t be overloaded.

The precedence of an operator:

The precedence of an operator is order of evaluation which operator will be evaluated first in expression.

The precedence of an operator is NOT affected due to overloading.

Example:

c1*c2+c3 c3+c2*c1

In both lines multiplication * will be done first and then addition.

Associativity:

Associativity is NOT changed due to overloading

Following arithmetic expression always is evaluated from left to right:

c1 + c2 + c3 + c4

Unary operators and assignment operator are right associative, e.g:

a=b=c is same as a=(b=c)

All other operators are left associative:

c1+c2+c3 is same as (c1+c2)+c3

Important things to consider:

Always write code representing the operator for example adding subtraction code inside the + operator will create chaos.

Creating a new operator is a syntax error (whether unary, binary or ternary), you cannot create $.

Arity of Operators

Arity (no of operands it works on) of an operator is NOT affected by overloading

Example:

Division operator will take exactly two operands in any case:

b = c / d

}

In case of non member functions of a class (in this case we will make overloaded operator function as friend function):

return_type operator operator_symbol( parameters ){

/*code*/

}

For example:

Complex& Complex::operator + (const Complex & c){

/*code*/

}

Complex& operator + (const Complex & c){

/*code*/

}

Binary Operators Overloading:

Binary operators act on two quantities.

Examples of binary operators:

General syntax of Binary Operators Overloading:

In case of member function of a class:

TYPE class_name::operator operator_symbol( TYPE rhs ){

/*code*/

}

In case of non-member function of a class:

TYPE class_name::operator operator_symbol( TYPE rhs1, TYPE rhs2 ){

/*code*/

class Complex{

private:

double real, img;

public:

Complex operator +(const Complex & rhs);

};

Complex Complex::operator +( const Complex & rhs){

Complex t;

t.real = real + rhs.real;

t.img = img + rhs.img;

return t;

}

The return type is Complex so as to facilitate complex statements like:

Complex t = c1 + c2 + c3;

The above statement is automatically converted by the compiler into appropriate function calls:

(c1.operator +(c2)).operator +(c3);

If the return type was void, class Complex{

...

public:

void operator+(

const Complex & rhs);

};

void Complex::operator+(const Complex & rhs){

real = real + rhs.real;

img = img + rhs.img;

};

We have to do the same operation c1+c2+c3 as:

c1+c2 c1+c3

// final result is stored in c1

Drawbacks of void return type:

Assignments and cascaded expressions are not possible One of the existing objects is used to store result

Code is less readable

Lecture No.17

Binary operators (cont.)

The binary operator is always called with reference to the left hand argument.

Example:

In c1+c2,

c1.operator+(c2)

// c1 is calling overloaded + operator and c2 is being passed as // reference in that function.

In c2+c1,

c2.operator+(c1)

// c2 is calling overloaded + operator and c1 is being passed as // reference in that function.

Adding basic data type to complex number class:

The overloading code we discussed before for complex no. class can add two complex number objects but it can not handle the following situation:

Complex c1;

c1 + 2.325 (as we are adding basic data type double to complex no.)

To do this, we have to modify the Complex class.

Modifying the complex class:

class Complex{

...

Complex operator+(const Complex & rhs);

Complex operator+(const double& rhs);

};

Complex operator + (const double& rhs){

Complex t;

t.real = real + rhs;

t.img = img;

return t;

argument

Now if we write the following two functions to the class, we can add a Complex to a real or vice versa :

Class Complex{

friend Complex operator + (const Complex & lhs, const double &

rhs);

friend Complex operator + (const double & lhs, const Complex &

rhs);

}

We have made them as friend so that we can write them as non member functions and they are not called with respect to complex no. class object instead we pass both arguments (complex no. object and double value) to this function compiler invoke them according to arguments passed. Their implementation is similar,

Complex operator +(const Complex & lhs, const double& rhs){

Complex t;

t.real = lhs.real + rhs;

t.img = lhs.img;

return t;

}

Complex operator + (const double & lhs, const Complex & rhs){

Complex t;

t.real = lhs + rhs.real;

t.img = rhs.img;

return t;

}

Binary operators

So adding three overloaded versions for + operator as shown below allow us to write code to,

Add two complex objects

Add complex object and a double value.

Class Complex{

Complex operator + (const Complex &);

friend Complex operator + (const Complex &, const double &);

Compiler searches overloaded operator code in member function first and then in non member functions.

Binary operators

Other binary operators are overloaded in similar to the + operator as demonstrated in the above examples

Example:

Complex operator * (const Complex & c1, const Complex & c2);

Complex operator / (const Complex & c1, const Complex & c2);

Complex operator - (const Complex & c1, const Complex & c2);

In document (OOP)_01-45(22-08-2009) updated.doc (Page 139-147)

Related documents