OPERATOR OVERLOADING – BCA Practical 2022

Fundamentals

  • There are many operators available that work on built-in types, like int and double.
  • Operator overloading — is the creation of new versions of these operators for use with user-defined types.
  • Operators usually refer to C++ predefined operators : 

» arithmetic operators: +, -, *, /, %
» relational operators: <, <=, ==, !=, >, >=
» assignment operator: =
» logical operators: &&, ||, !
» input/output operators: <<, >>

  • It is not as difficult as it Some things to note :

» An operator in C++ is just a function that is called with special notation (usually more intuitive or familiar notation). Overloading an operator simply involves writing a function.
» C++ already does some operator overloading implicitly on built-in types. Consider the fact that the + operator already works for ints, floats, doubles, and chars. There is really a different version of the + operator for each type.

Operator overloading is done for the purpose of using familiar operator notation on programmer-defined types (classes).

Read More – ARRAYS AND STRINGS

                        PRACTICAL MANUAL ON C ++

Some rules regarding operator overloading

  • Overloading an operator cannot change its precedence.
  • Overloading an operator cannot change its associativity.
  • Overloading an operator cannot change its “arity” (i.e. number of operands) You cannot change the number of arguments that an operator takes.
  • It is not possible to create new operators — only new versions of existing ones.
  • Operator meaning on the built-in types cannot be changed.
  • The following operator can only be overloaded as member functions: =, [], -> and ().
  • The following operator cannot be overloaded: the dot operator (.), the scope resolution operator (::), sizeof, ?: and .*.
  • An overloaded operator cannot have default arguments.

Format

  • An operator is just a function. This means that it must be created with a return type, a name, and a parameter list
  • The rules above give some restrictions on the parameter list
  • The name of an operator is always a conjunction of the keyword operator and the operator symbol itself. Examples :

» operator +
» operator ++
» operator <<
» operator ==

  • So the format of an operator overload declaration is just like that of a function, with the keyword operator as part of the name :

return Type operator Operator Symbol ( parameter List ) ;

Overloading operator implementation

  • Operations for C++ primitive data types (such as int, char and double) are predefined in C++ language.

int main  (  )
{
int  x , y = 3 ;
x = y + 10 ; // OK ( int + int ) , other arithmetic operators – , *,  / ,
%
// also OK  ( int = int ) — assignment
if ( x  <  y ) // OK  ( int < int ) , other logical operators <  =  ,  >  ,  >  =  ,
==  ,  !  =

  • But, for user-defined data types (Classes), C++ doesn’t have definitions for those operators.

class Money
{
public :
Money (  ) ;
Money  (  int d , int c  ) ; Money  (  int allc  ) ;
double getAmount  (  ) ; // Returns the amount as a double
void printMoney  (  ) ; // prints a money to cout , in the form $xx.yy private :
int dollar ; int cent ;
} ;
int main (  )
{
Money m1 (  3 , 25  ) , m2  (  19 , 5  ) ;
Money m3 = m1 + m2 ; // SYNTAX ERROR !! operator + is not defined for Money
cout  <<  m1 ; // SYNTAX ERROR !! operator  <<   is not defined for Money

  • An Operator is essentially a function. So, we can look at expressions with operators as function call. Those functions have operator keyword in front of them (in prefix notation).

x = x + 5 ; // infix notation, same as : x = operator + ( x , 5 ) ;
cout << x ; // infix notation , same as : operator << ( cout , x ) ;

  • So if you want to use familiar syntax with classes, you must write the definition for the (overloading) operators for the

The Thee ways

  • There are 3 ways to define overloaded operators :
  1. Member function
  2. Nonmember function
  3. Friend function

 

Member function

  • The first way is by class method (member function). This is the most popular way.Many experts advocate always overloading operators as member operators rather than as nonmembers. It is more in the spirit of object-oriented programming and is a bit more efficient since the definition can directly reference member variables.”
  • Since the operator is applied on a (existing) class object, the number of parameters to the operator is one less :

» Binary operators have 1 parameter, the second operand to the The first operand is the object in which the overloaded operator is called/invoked.

» Unary operators (e.g. unary – for negative) have 0 parameter.

Example : –

//  filename : money.h — Header file for class Money

# ifndef MONEY  _  H
# define MONEY  _  H

# include <  iostream  > using namespace std  ;

class Money
{
public  :
Money  (   )  :  dollar  (  0  )  , cent  (  0   )  {   }
Money  ( int d ,  int  c ) : dollar  (  d  ) , cent  (  c  )  {  } Money  (  int allc  ) ;

Money  operator  +  ( const Money & mo2  )  const ;
Money  operator – (  const Money  &  mo2 )  const ;  //  binary – Money  operator – ( )  const  ;  // unary  –  bool  operator  ==  ( const  Money & mo2 )  const ;

bool  operator  <=  (  const Money & mo2  )  const ;

int  get Dollars  (  )  const { return dollar ;  }  int  get Cents (  ) const  { return cent ; }

// friend functions
friend  ostream  &  operator << ( ostream & out ,  const  Money  &  m ) ; friend istream & operator >> ( istream & in , Money  &  m ) ;
friend bool operator > ( const  Money  & ,  const  Money  & ) ;

private :
int dollar ;  int cent ;
} ;

//  prototypes of overloaded operators implemented as
//  regular functions
bool operator < (  const  Money  & , const  Money  & ) ; bool operator ! = ( const Money  & , const Money & ) ;

# endif

_____________________________________________________________________________________________________________________________

// filename : money.cpp — Implementation file for class Money

#include  ” money.h” Money::Money(int allc)
{
dollar = allc / 100; cent = allc % 100;
}

Money Money :: operator+(const Money & m2) const

{
int total = (dollar * 100 + cent) +
(m2.dollar * 100 + m2.cent); Money local(total);
return local;
}

 

Money Money :: operator-(const Money & m2) const // *this – mo2
{
int diff = (dollar * 100 + cent) –
(m2.dollar * 100 + m2.cent); Money local(diff);
return local;
}

Money Money::operator-() const // unary –
{
int neg = – (dollar * 100 + cent); Money local(neg);
return local;
}

bool Money::operator==(const Money & m2) const
{
int thistotal = (dollar * 100 + cent);
int m2total = (m2.dollar * 100 + m2.cent); return (thistotal == m2total);
}

bool Money::operator<=(const Money & m2) const
{
int thistotal = (dollar * 100 + cent);
int m2total = (m2.dollar * 100 + m2.cent); return (thistotal <= m2total);
/*
if (*this < m2 || *this == m2) return true;
else
return false;
*/
}

// no keyword “friend” in the function definition ostream& operator<<(ostream& out, const Money & m)
{
out <<
<< “$” << m.dollar “.” << m.cent; // dollar private in m — OK
// cent private in m — OK

} return out;

istream& operator>>(istream& in, Money & m)
{
char dollarSign; double moneyAsDouble;

in >> dollarSign; // first eat up ‘$’ in >> moneyAsDouble; // xx.yy

m.dollar = static_cast<int>(moneyAsDouble);
m.cent = static_cast<int>(moneyAsDouble * 100) % 100;

return in;
}

// friend function
bool operator>(const Money & m1, const Money & m2)
{
int thistotal = m1.dollar * 100 + m1.cent; int m2total = m2.dollar * 100 + m2.cent; return (thistotal > m2total);
}

bool operator<(const Money & m1, const Money & m2) // note: 2 arguments and NO Money::
{
int thistotal = m1.getDollars() * 100 + m1.getCents(); int m2total = m2.getDollars() * 100 + m2.getCents(); return (thistotal < m2total);
}

bool operator!=(const Money & m1, const Money & m2)
{
int thistotal = m1.getDollars() * 100 + m1.getCents(); int m2total = m2.getDollars() * 100 + m2.getCents(); return (thistotal != m2total);
}

_____________________________________________________________________________________________________________________________

//  filename :  myMoneyApp.cpp
//
// An application program which uses Money objects  (  defined in
//  ” money. h ” ) .

#include <  iostream  >
using namespace std  ;
# include “money.h  ”  int main  (  )
{
Money m1 (  2 , 98  ), m2  (  15  ,  2  )  , m3  ;

m3  =  m1  +  m2  ;   // member function operator  +
cout   <<   m1   <<   ”   +   ”   <<   m2   <<   ”   =   ”   <<   m3   <<   endl  ;   if   ( m1   !  =  m2  )
cout   <<   ”  Not equals.  \n  ”  ;
else
cout   <<   ”  Equals.  \n  ”  ;

if   (  m1   >   m2  )
cout   <<   ”  Greaterthan.  \n  ”  ;
else
cout   <<   ”  NOT Greaterthan.  \n  ” ;

bool ans   =  m1  > m2  ;
cout  <<   ans   <<   endl  ;   // prints 0   ( false  ) or 1  (  true  )

system  (  ”  pause  ”  ) ;
return 0  ;
}

Run time ouput :-

$2.98  +  $15.2  =  $18.0
Not equals.
NOT Greaterthan.
0

Top-level (Nonmember) function

  • Another way to overload operators is by regular, non-member functions.
  • Another way to overload operators is by regular, non-member functions.

        »  Binary operators have 2 parameters, the second operand to the The first operand is the object in which the overloaded operator is called/invoked.

        »   Since the operator is NOT a class method, all operands involved in the operator become the parameters :

»  Unary operators have 1 parameter.

  • Also the operator cannot access private members in the parameter objects.

class Money

{

public :

Money (  )  ;

Money  (  int  d ,  int   c  ) ;

Money   (  int   allc  ) ;

int getDollars  (   )  const ;

int getCents  (   )  const ;

// note  :  NO method for operator  <

private  :

int dollar  ;

int cent  ;

}  ;

// Definition of regular  ,  non-member functions.

// mo1  <  mo2

bool operator  <  (  const Money  &  m1, const Money  &  m2  )  //  note  :  2

arguments and NO Money  ::

{

int thistotal  =  m1.getDollars   (  )  * 100  +  m1.getCents  (   ) ;

int m2total  =  m2.getDollars  (   )   * 100  +  m2.getCents  (   ) ;

return  (  thistotal  <  m2total  )  ;

}

Friend function

  • Yet another way is to use friend function. Friend functions are declared within a class, but they are NOT class
  • A friend function is actually a regular function which has a privilege to access private members in the parameter objects.

class Money

{

public  :

Money  (   )  ;

Money   (   int d ,  int c  )  ;

Money   (   int allc  )  ;

Money operator  +  (  const Money & mo2  )  const  ;

//  friend functions

friend ostream& operator  <<  (  ostream& out ,  const Money & m  )  ;  // to be able to do cout   <<  obj

friend istream & operator  >>  (  istream& in , Money & m  )  ;   // to be able to do cint   >>   obj

private  :

int dollar  ;

int cent  ;

}  ;

//  no keyword “friend ”  in the function definition ostream &  operator  <<  (  ostream&  out , const  Money  & m )

{

out  <<   “$”  <<   m.dollar  // dollar private in m  —  OK

<<   “.”   << m.cent  ;    // cent private in m — OK

return out;

}

istream& operator   >>  (  istream& out  , Money & m )

{

char dollarsign  ;

double moneyAsDouble  ;

in   >>  dollarSign  ;    // first eat up  ‘$’

in   >>  moneyAsDouble  ;   //   xx.yy

m.dollar  =  static _ cast <int>  (  moneyAsDouble  ) ;

m.cent  =  static  _  cast  <  int  > (  moneyAsDouble  *  100  )  %  100  ;

return in  ;

}