Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 17

Chapter 5

Operator overloading
Operator overloading is one of the features of C++ language. The concept by which we can give
special meaning to an operator of language is known as operator overloading. For example +
operator in C++ work only basic type like int and float means; c=a+b is calculated by compiler if
a, b and c are basic type. Suppose that if a, b and c are objects of user defined class compiler give
error. However using operator overloading we can make this statement legal even if a, b and c
are object of class. Therefore operator overloading enabling C++’s operators to work with class
objects, since it permit us to define the behaviour of operators when applied to objects of a class.
C++ allows the programmer to extend the definitions of most of the operators to work
with classes by overloading the operator and to define additional meanings for its predefined
operators by overloading them. There are two types of operators to overload:
1. Unary
2. Binary
Unary operators are the ones that require only one operator to work. Unary operators are applied
to the left of the operand. For example, ^, &, ~and !.
Binary operators require two operands on both sides of the operator. +,-,*,/,%,=,< and >are
examples of binary operators.
5.1. Declaration of operator overloading
The declaration of operator overloading is done with the help of a special function called
operator function. The operator is a keyword in C++.the general format of the operator function
is:
return_type operator oper(Parameter list){
body of the function which defined task
}
In the above declaration operator is a keyword and oper is the operator to be used in the function
like +,-,*, etc.
Here you have an example that includes the operator +. We are going to sum the bi-dimensional
vectors a (3,1) and b(1,2). The addition of two bi-dimensional vectors is an operation as simple
as to add the two x coordinates to obtain the resulting x coordinate and to add the two y

Fundamental of programming II Page 1


coordinates to obtain the resulting y. In this case the result will be (3+1, 1+2) = (4, 3) as shown in
program5.1 below.

//program5.1:overloadingoperators example 4,3

#include <iostream.h>
class CVector {
public:
int x,y;
CVector () {
};
CVector (int,int);
CVector operator + (CVector);
};
CVector::CVector (int a, int b) {
x = a;
y = b;
}
CVectorCVector::operator+ (CVector param) {
CVector temp;
temp.x = x + param.x;
temp.y = y + param.y;
return (temp);
}
int main () {
CVector a (3,1);
CVector b (1,2);
CVector c;
c = a + b;
cout << c.x << "," << c.y;
return 0;
}

Fundamental of programming II Page 2


In the above program CVector consider that some of them make reference to the class name
CVector and others are functions with that name (constructor and destructor).

CVector (int, int); // function name CVector (constructor)


CVector operator+ (CVector); // function operator+ that returns CVector type
The function operator+ of class CVector is the one that is in charge of overloading the arithmetic operator
+. This one can be called by any of these two ways:
c=a+b;
c = a.operator+ (b);

The following table 5.1. Show a summary on how the different operator functions must be
declared (replace @ by the operator in each case):

Expression Operator (@) Function member Global function

@a + - * & ! ~ ++ -- A::operator@() operator@(A)

a@ ++ -- A::operator@(int) operator@(A, int)

+-*/%^&|<
a@b > == != <= >= A::operator@(B) operator@(A, B)
<< >> && || ,

= += -= *= /=
a@b %= ^= &= |= A::operator@(B) -
<<= >>= [ ]

a (b, c...) () A::operator ()(B, C...) -

a->b -> A::operator->() -

* Where a, b and c are objects of the user defined class.


You can see in this table that there are two ways to overload some class operators: as member
function and as global function. Its use is indistinct; nevertheless it is better to remind you that

Fundamental of programming II Page 3


functions that are not members of a class cannot access the private or protected members of the
class unless the global function is friend of the class.

Table 5.2
Generally the above listed operator in the table 5.2 can be overloaded in the user defined class
whereas the following operators are not overloaded in C++ as shown in table 5.3

Table 5.3 List of operator that cannot be overloaded


5.2. Operator Functions
We overload operators by creating operator function. An operator function defines the specific
operations that the overloaded operator will perform relative to the class it is designed to
work on. Operators can be members or non-members to the class. The member operator
functions are using this operator to achieve its work. While the non-member operator functions
are almost always friend functions of a class. When we define a class, only the member functions
can access the private fields of that class. A member function just uses the variable directly, it’s

Fundamental of programming II Page 4


already declared in the class private section. These are called implicit variables. For example in
the following code fragment the implicit and explicit variable were identified.

 To prevent a member function from changing an implicit parameter, add the word const to
the function.
void Point::move (double dx, double dy) const; // Can’t make changes to x, y
void Point::move (double dx, double dy); // Can change the implicit parameters x, y
 For non-member functions, we have to add an & to change the value of an explicit
parameter.
void move (double& dx, double& dy); // Can change explicit reference parameters dx, dy
void move (double dx, double dy); // Can’t change explicit value parameters dx, dy

The following table 5.4 the summary of explicit and implicit variables with respect to the values
changes

Fundamental of programming II Page 5


5.3. Operator Overloading with the Member Operator Functions
 If you write an operator function as a member function, then it automatically has access to all
of the member variables and functions of the class.
 when an operator function is implemented as a member function, the leftmost operator must
be a class object or reference to a class object of the operator’s class
 The following is a simple example of operator overloading. In this example, the program
creates a class xyCoords, which stores xc and yc coordinate values. It overloads the +
operator relative to this class.

Q. Write an OO-Program to overload the + operator, using member overloading function


//program 5.2 overloading + operator member function
#include<iostream.h>

Fundamental of programming II Page 6


class xycoords{
int xc , yc;
public:
xycoords ( ) { };
xycoords (int x , int y) {
xc = x ; yc = y ;
}
void display( ){
cout << xc <<" " << yc<<endl;
}
xycoords operator + (xycoords op1);
};
xycoords xycoords :: operator + (xycoords op1){
xycoords temp;
temp.xc = op1.xc + xc;
temp.yc = op1.yc + yc;
return temp;
}
int main( ){
xycoords ob1(5,10);
xycoords ob2(20,30);
xycoords ob3( 0, 0);
ob3.display( ); Output :
ob3 = ob1 + ob2;
ob3.display( );
return 0;
}

The operator+ ( ) function has only one parameter even though it overloads the binary +
operator. The reason that operator+ ( ) function takes only one parameter is that the

Fundamental of programming II Page 7


operand on the left side of the + is passed implicitly to the function using this pointer.
The operand on the right is passed in the parameter op1.When you overload a binary
operator (like + operator) by using a member function, the object on the left side of the
operator generates the call to the overloaded operator function.
The following Operators must be overloaded as members

 = assignment operator • Q: can we write a non-member


operator function without making it a friend
 [] subscript operator
of a class.
 () function call operator • Answer: yes; if there are public
member functions to access the private data
 -> indirect member access operator members of the class then they serve the
purpose.
 ->* indirect pointer to member access
• The following program 5.3 rewrites
operator
the above mention program 5.2 to show how
5.3.1. Operator Overloading with the can we overload nonmember function
Nonmember Operator • #include<iostream.h>
Functions(Friend Function) • class xycoords{
• Since a friend function is not a • int xc , yc;
member of the class, it does not have this • public:
pointer. Therefore, an overloaded friend • xycoords ( ) { };
operator function is passed the operands • xycoords (int x , int y) { xc
explicitly. This means that a friend which = x ; yc = y ; }
overloads a binary operator has two • void display( ) { cout <<
parameters. xc <<" " << yc<<endl; }
 All operands must be explicitly specified • friend xycoords operator+ (xycoords
as formal arguments. op1, xycoords op2);
 For binary operators, either the first or • };
the second must be an object of a class; • xycoords operator+ (xycoords op1,
the other operand can be any type. xycoords op2){
• xycoords temp;
• temp.xc = op1.xc + op2.xc;
Fundamental of programming II Page 8
• temp.yc = op1.yc + op2.yc; (invalid expression). Using non-member
• return temp; friend function will be solving this problem.
• } • The following program 5.4 overload
• int main( ){ + operator, for the object and integer type.
• xycoords ob1(5,10); • #include<iostream.h>
• xycoords ob2(20,30); • class xycoords{
• xycoords ob3( 0, 0); • int xc , yc;
• ob3.display( ); • public:
Output •
• ob3 = ob1 + ob2; oord
• ob3.display( ); s ( )
• return 0; { };
• } • xycoords (int x , int y) { xc = x ; yc =
• Since a friend function is not a y;}
member of the class, it does not have this • void display( ) { cout << xc << “ “
pointer. However, the friend function << yc; }
increases the flexibility of an overloaded • friend xycoords operator+ (xycoords
operator. For example, the following op1, int op2);
expression ( Op1 + 5 ) is valid when • friend xycoords operator+ (int op1,
using member friend function. In this xycoords op2);
case, op1 generates the call to the • };
overloaded + function, and the addition • xycoords operator+ (xycoords op1,
is performed. int op2){
• But what happens when the • xycoords temp;
following expression (5 + Op1) is written. In • temp.xc = op1.xc + op2;
this case, it is the integer that appears on the • temp.yc = op1.yc + op2;
left. Since an integer is built-in type, no • return temp;
operation between an integer and an object • }
of op1’s type is define. Therefore, the • xycoords operator+ (int op1,
compiler will not compile this expression xycoords op2){
• xycoords temp;

Fundamental of programming II Page 9


• temp.xc = op1 + op2.xc; << to output values of various types,
• temp.yc = op1 + op2.yc; such as long, double and so on. Similar
• return temp; remarks apply to the input operator (>>).
• } • The declaration of << for the
• void main( ){ output of int values has the following
• xycoords ob1(5,10); form:
• xycoords ob2(20,30); •
output
• xycoords ob3( 0, 0);
• ob3.display( );
• ob3 = ob1 + 5; //valid
• ob3.display( );
• ob3 = 5 + ob2; //valid • The arguments of the function
• ob3.display( ); correspond to the operands of the operator.
• } Thus, the operator << takes an output stream
as its first operand and, for example, the
• Both arguments are explicitly passed
integer to be outputted as its second. The
to the operator function. Therefore, to allow
output stream must be passed by reference
both object +integer and integer +object,
because its internal state will be
simply overload the function twice-one
modified by the output operation. The <<
version for each situation. Thus, when you
operator always return a reference to its
overload an operator by using two friend
first operand, the output stream c; this
functions, the object may appear on either
property enables us to use several <<
the left or right side of the operator.
operators in succession.
5.4. Overload the Output • cout << 50; invokes the code for
Operator(<<) outputting an int value.
• The header file iostream.h declares • While cout << 8.5; invokes the
a class ostream of output streams and code for outputting an double value.
provides a number of definitions for << • It is quite easy to define an output
where its first operand is an ostream operator for types of our own invention. For
object. These definition allow us to use example, suppose we define the class

Fundamental of programming II Page 10


date, and declare the date variable d as • friend ostream&
following, we could like the statement operator<<(ostream&, const Sale&);
( cout << d; ) to print, for example, • The operator <<()function is a friend
5/3/2010. to the Sale class. It receives a reference to an
• Declare class with class name of ostream object and a reference to a Sale. The
date: Sale reference can be defined as const
• Class date { because the output should not alter the
• int day; Sale’s data. The contents of the function
• int month; body can display a Sale with any desired
• int year; text and in any format you want.
• }; date d = {10, 3, 2008} //create an • For example, the following code
object of date d with initialized value fragment shows a usable operator
of day, month and year. <<()function for the Sale class.
• We can define such an output • ostream& operator<<(ostream& out,
operator (overload << operator) for date const Sale& aSale){
objects as follows: • out << "Sale #" <<
• Overload << operator for date’s aSale.receiptNum <<
object: • " for $" <<
• ostream& operator<< (ostream& c, aSale.saleAmount << endl;
date d){ • return out;
• c << d.day << “/”; •}
• c << d.month << “/”; • Here, the class name Sale and the
• c << d.year; scope resolution operator do not appear in
• return c; the function header. The operator<<()
• } function is not a member of the Sale class.
• Additionally, to overload the Instead, it is a non-member friend function
<<operator so it can work with a Sale object, so that the operator can access the private
you must add the overloaded operator << () members of the ostream class and the Sale
function prototype to the Sale class. class, and then operate like the built-in
• The prototype is: versions of <<. Because operator<<()is not a
member of the Saleclass, you cannot output

Fundamental of programming II Page 11


the values receiptNum and saleAmount • The following program 5.5 shows a
without using a Sale object and a dot Sale class and a main()function that declares
operator. Because it is not a Sale class a Saleobject.
member, the operator<<()function does not
• #include<iostream.h>
receive a this pointer. Therefore, it cannot
• class Sale{
directly refer to any controlling object’s data
• friend ostream&
by just using a field name. The data that
operator<<(ostream&, const Sale&);
displays is the data that belongs to the
• private:
argument named aSale, which is the
• int receiptNum;
argument that appears to the right of << in a
• double saleAmount;
cout statement.
• public:
• NOTE The “out” in the operator
• Sale(int, double);
<<()definition in the above code fragment is
//constructor
not a keyword. It is a programmer-chosen
• };
local name for the reference to ostream, just
• Sale::Sale(int num, double
as aSale is a local name for the Sale object.
sale){
You can use any legal C++ variable name
• receiptNum = num;
you choose.
• saleAmount = sale;
• After you include the overloaded
• }
operator<<()function in the Saleclass, any
• ostream&
function that includes a Sale object
operator<<(ostream& out, const
declaration such as Sale aShirt; can
Sale& aSale)
subsequently use a statement such as cout
• {
<< aShirt;to display the aShirtobject’s data.
• out << "Sale #" << aSale.receiptNum
The statement that uses cout is only a few
<<
characters shorter than aShirt.showSale();,
• " for $" << aSale.saleAmount <<
but the statement makes Saleappear to be a
endl;
built-in data type. Using the overloaded
• return out;
<<operator allows the use of simpler
• }
program statements.
• int main(){

Fundamental of programming II Page 12


• Sale aShirt(1567, 39.95); iostreamfile along with ostream) by using a
output prototype as follows:
• cout << aShirt;
• return 0;
• }
• friend istream&

operator>>(istream&, Sale&);
• The first shaded statement is the
• Within the preceding function, it is
prototype for the friend function. As a non-
appropriate to code statements that retrieve
member function, it could have been
Sale values from an input device. For
declared anywhere within the class. The
example, you might choose to create
second shaded line is the
prompts and data entry statements that allow
operator<<()function header. The body of
a user to enter values for any or all of a
the function displays the Sale object details
Sale’s data fields. The parameters to the
in whatever form the programmer decides is
operator>>() function are an istream object
useful. The third shaded line shows how the
and a Sale object. Unlike the operator<<()
overloaded insertion operator is used with a
function, the Sale object that receives data
Sale object.
values cannot be passed to this function as a
5.5. Overloading the
constant. That’s because this function needs
Input Operator(>>)
to change Sale’s data values through
• If the insertion operator (<<) can be
keyboard data entry.
overloaded for output, it makes sense that
• The following code fragment shows
the extraction operator (>>) also can be
the implementation of the
overloaded for input using the
operator>>()function for the Sale class.
operator>>()function. The advantage of
overloading operators such as >>is that the • istream& operator>>(istream&
resulting programs look cleaner and are in, Sale& aSale){
easier to read. Consider the Saleclass that • cout << endl; // to clear the
contains a receiptNumand a saleAmount. buffer
You can create an extraction operator, or • cout << "Enter receipt
operator>>()function, that uses the number ";
istreamclass (which is defined in the • in >> aSale.receiptNum;

Fundamental of programming II Page 13


• cout << "Enter the amount • ostream&
of the sale "; operator<<(ostream& out, const
• in >> aSale.saleAmount; Sale& aSale){
• cout << endl << " Thank • out << "Sale #" <<
you!" << endl; aSale.receiptNum << " for $" <<
• return in; aSale.saleAmount << endl;
• } • return out;
• Program 5.6 shown below • }
demonstrates how the output and input • istream&
operator can be overloaded in one program. operator>>(istream& in, Sale&
• //program 5.6 aSale){
• #include<iostream.h> • cout << endl; // to clear the
• class Sale{ buffer
• friend ostream& • cout << "Enter receipt
operator<<(ostream&, const Sale&); number ";
• friend istream& • in >> aSale.receiptNum;
operator>>(istream&, Sale&); • cout << "Enter the amount
• private: of the sale ";
• int receiptNum; • in >> aSale.saleAmount;
• double saleAmount; • cout << endl << " Thank
• public: you!" << endl;
• Sale(int, double); • return in;
//constructor • }
• }; • int main(){
• Sale::Sale(int num, double • Sale aShirt(0, 0);
sale){
• receiptNum = num;
• saleAmount = sale;
• }
Output:
• cin >> aShirt;
• cout << aShirt;

Fundamental of programming II Page 14


• return 0; • return arr[i];
• } • }
5.6. Subscripting [] • };
operator overloading •
in C++ • int main(){
• The subscript operator [] is normally • safearay A;
used to access array elements. This operator • cout << "Value of A[2] : " <<
can be overloaded to enhance the existing A[2] <<endl;
functionality of C++ arrays. Following output
example explains how a subscript operator [] •
can be overloaded. cout <<
"Value of A[5] : " << A[5]<<endl;
• //program 5.7
• cout << "Value of A[12] : " <<
• #include <iostream.h>
A[12]<<endl;
• const int SIZE = 10;
• return 0;
• class safearay
• }
• { private:
5.7. Overloading
• int arr[SIZE];
Increment ++ and
• public:
Decrement - -
• safearay()
• The increment and decrement
• { register int i;
operators are unary operators that can be
• for(i = 0; i < SIZE; i++) {
overloaded for prefix as well as postfix
• arr[i] = i;
usage. When you overload any C++
• }
function, you must supply different
• }
parameter lists; for the postfix ++operator to
• int &operator[](int i) {
distinguish from prefix (you use an integer
• if( i > SIZE ) {
parameter). For instance The Inventory class
• cout << "Index out of
postfix operator++()function prototype is:
bounds" <<endl;
• Inventory& operator++ (int);// the
• return arr[0]; // return
same fashion for postfix --
first element.
• }
Fundamental of programming II Page 15
• The following program5.8 shows the • minutes -= 60;
use of postfix and prefix increment operator • }
overloading • return Time(hours, minutes);
• //program 5.8 • }
• #include <iostream.h> • Time operator++( int ) { ///
• class Time{ overloaded postfix ++ operator
• private: • Time T(hours, minutes); //
• int hours; // 0 to 23 // save the orignal value
• int minutes; // 0 to 59 • ++minutes; // //
• public: increment this object
• Time(){ // required • if(minutes >= 60) {
constructors • ++hours;
• hours = 0; • minutes -= 60;
• minutes = 0; • }
• } • return T; // return old original
• Time(int h, int m){ // value
parameterized constructor • }
• hours = h; minutes = m; • };
• } • int main(){
• void displayTime(){ // • Time T1(11, 59), T2(10,40);
method to display time • ++T1; // increment T1
• cout << "H: " << hours << " M:" • T1.displayTime(); // display
<< minutes <<endl; T1
• } • ++T1; // increment T1
• Time operator++ () again
{ /// // overloaded prefix ++ • T1.displayTime(); // display
operator T1
• ++minutes; // increment • T2++; // increment T2
this object • T2.displayTime(); // display
• if(minutes >= 60) { T2
• ++hours;

Fundamental of programming II Page 16


• T2++; // increment T2
again
• T2.displayTime(); // display
T2
• return 0;
• }
• What will be the output of the above
program?

Fundamental of programming II Page 17

You might also like