0% found this document useful (0 votes)
8 views

04 Operator Overloading

The document discusses operator overloading in C++. Operator overloading allows operators like + and ++ to be used with user-defined types rather than just basic types. It allows functions to be called when those operators are used on objects of a class. Specifically, it covers overloading unary operators like ++ to increment objects of a Counter class. It discusses ensuring operator functions return a value when needed, such as for assignments.

Uploaded by

Dann Laurte
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views

04 Operator Overloading

The document discusses operator overloading in C++. Operator overloading allows operators like + and ++ to be used with user-defined types rather than just basic types. It allows functions to be called when those operators are used on objects of a class. Specifically, it covers overloading unary operators like ++ to increment objects of a Counter class. It discusses ensuring operator functions return a value when needed, such as for assignments.

Uploaded by

Dann Laurte
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 57

OPERATOR

OVERLOADING

SCHOOL OF COMPUTING MITCH M. ANDAYA


BASIC PRINCIPLES

• Recall in the previous chapter:

len3.add_length (len1, len2);

and

len3 = len1.add_length (len2);

add two objects of class length, len1 and len2, and stores
the result in another object, len3.

Both instructions are kind of obscure.

Operator Overloading
BASIC PRINCIPLES

• Operator overloading can transform complex, obscure program


listings into intuitively obvious ones such as:

len3 = len1 + len2;

• Operator overloading refers to giving the normal C++ operators,


such as +, *, <=, and +=, additional meanings when they are
applied to user-defined data types.

• Normally, a = b + c works only with basic types such as int and


float, and attempting to apply it when a, b, and c are objects of a
user-defined class will cause complaints from the compiler.

• However, using overloading, a programmer can make this


statement legal even when a, b, and c are user-defined types.

Operator Overloading
BASIC PRINCIPLES

• In effect, operator overloading gives the


programmer the opportunity to redefine the C++
language.

• If the way the C++ operators work causes


limitations, the programmer can change them to
do whatever he wants.

• By using classes to create new kinds of variables,


and operator overloading to create new definitions
for operators, C++ can be extended to be a new
language.
Operator Overloading
OVERLOADING UNARY OPERATORS

• Recall the counter example of the previous chapter:

#include <iostream>
using namespace std;

class counter
{
private:
int count;

public:
counter() : count(0)
{ }
void inc_count()
{ count = count + 1; }
int get_count()
{ return count; }
};

Operator Overloading
OVERLOADING UNARY OPERATORS

main()
{
counter c1, c2;

cout << "\nc1= " << c1.get_count();


The output of this
cout << "\nc2= " << c2.get_count(); program is:
c1.inc_count(); c1=0
c2.inc_count(); c2=0
c2.inc_count(); c1=1
c2=2
cout << "\nc1= " << c1.get_count();
cout << "\nc2= " << c2.get_count();
}

Operator Overloading
OVERLOADING UNARY OPERATORS

• Recall that unary operators act on only one operand (an operand is
simply a variable acted on by an operator). Examples of unary
operators are the increment and decrement operators ++ and --,
and the unary minus, as in -33.

• In the counter example, objects of class counter were incremented


by calling the member function inc_count(). So to increment the
object c1, the function c1.inc_count() is invoked.

• The instruction would have been more readable if the increment


operator ++ could have been used instead: ++c1;

• All C++ (and C) programmers would guess immediately that this


expression increments c1.

Operator Overloading
OVERLOADING UNARY OPERATORS

• Revised Counter Program (using overloaded operators)

#include <iostream>
using namespace std;

class counter
{
private:
int count;
The keyword operator is used to
public: overload the ++ operator.
counter() : count(0)
{ } This declarator syntax tells the
void operator ++ () compiler to call this member function
{ count = count + 1; } whenever the ++ operator is
int get_count()
encountered, provided the operand
{ return count; }
(the variable operated on by the ++) is
};
of type counter.

Operator Overloading
OVERLOADING UNARY OPERATORS

main()
The ++ operator is applied to a
{
specific object, as in the
counter c1, c2;
expression ++c1.

cout << "\nc1= " << c1.get_count(); The operator ++() takes no
cout << "\nc2= " << c2.get_count(); arguments.

++c1; It increments the count data in


++c2; the object of which it is a
++c2; member. Since member
functions can always access the
cout << "\nc1= " << c1.get_count(); particular object for which
cout << "\nc2= " << c2.get_count(); they’ve been invoked, this
} operator requires no
arguments.

Operator Overloading
OPERATOR RETURN VALUES

• In the previous example, the statement:

c1 = ++c2;

will result in a compilation error.

• This is because the ++ operator was defined to have a return type of void in the
operator++() function, while in the assignment statement it is being asked to
return a variable of type counter. That is, the compiler is being asked to return
whatever value c2 has after being operated on by the ++ operator, and assign
this value to c1.

• So as defined in the program, the ++ operator cannot be used to increment


counter objects in assignments; it must always stand alone with its operand.

• Of course the normal ++ operator, applied to basic data types such as int, would
not have this problem.

Operator Overloading
OPERATOR RETURN VALUES

• Revised Counter Program (using overloaded operators with return values)

#include <iostream>
using namespace std;

class counter
{
private:
int count;

public:
counter() : count(0)
{ }
int get_count()
{ return count; }

Operator Overloading
OPERATOR RETURN VALUES

counter operator ++ () Here the operator++ ()


{ function creates a new object
of type counter, called temp,
counter temp; to use as a return value.

It increments the count data


++count; in its own object as before,
temp.count = count; then assigns count in the new
object temp the same value
return temp; as in its own object.
}
Finally, it returns the temp
}; object.

Operator Overloading
OPERATOR RETURN VALUES

main() The expression ++c1 now


{ returns a value, so it can be
counter c1, c2; used in other expressions,
such as c2 = ++c1; where
the value returned from
cout << "\nc1= " << c1.get_count(); ++c1 is assigned to c2.
cout << "\nc2= " << c2.get_count();
The output of this program
++c1; is:
c2 = ++c1;
c1=0
cout << "\nc1= " << c1.get_count(); c2=0
cout << "\nc2= " << c2.get_count(); c1=2
} c2=2

Operator Overloading
OPERATOR RETURN VALUES

counter operator ++ ()
• Nameless Temporary Objects
{
++count;
counter operator ++ () return (counter (count));
{ }
counter temp;
This statement creates an
++count; object of type counter. This
temp.count = count; object has no name; it will
return temp; not be around long enough
to need one. This unnamed
} object is initialized to the
value provided by the
argument count.

Operator Overloading
OPERATOR RETURN VALUES

• But this requires a constructor that takes one argument.

#include <iostream>
using namespace std;

class counter
{
private:
int count;
public:
counter() : count(0)
{ }
counter (int c) : count(c)
{ }
int get_count()
{ return count; }

Operator Overloading
POSTFIX NOTATION

• Revised Counter Program (using overloaded ++ operator with postfix notation)

#include <iostream>
using namespace std;

class counter
{
private:
int count;
public:
counter() : count(0)
{ }
counter (int c) : count(c)
{ }
int get_count()
{ return count; }

Operator Overloading
POSTFIX NOTATION

counter operator ++ () The only difference is the int in


{ the parentheses. This int is not
really an argument, and it does
++count; not mean integer.
return counter (count);
} It is simply a signal to the
compiler to create the postfix
counter operator ++ (int) version of the operator.
{
++count; The designers of C++ are fond
return counter (count); of recycling existing operators
} and keywords to play multiple
roles, and int is the one they
}; chose to indicate postfix.

Operator Overloading
POSTFIX NOTATION

main()
{
counter c1, c2;

cout << "\nc1= " << c1.get_count();


The output of this program is:
cout << "\nc2= " << c2.get_count();
c1=0
++c1;
c2=0
c2 = ++c1;
c1=2
cout << "\nc1= " << c1.get_count();
c2=2
cout << "\nc2= " << c2.get_count();
c1=3
c2=2
c2 = c1++;
cout << "\nc1= " << c1.get_count();
cout << "\nc2= " << c2.get_count();
}

Operator Overloading
OVERLOADING BINARY OPERATORS

• Recall the Length Program

#include <iostream>
using namespace std;

class length
{
private:
int feet;
float inches;

public:
length () : feet (0), inches (0.0)
{}
length (int ft, float in) : feet(ft), inches(in)
{}

Operator Overloading
OVERLOADING BINARY OPERATORS

void getlength()
{
cout << "\nEnter Feet: ";
cin >> feet;
cout << "Enter Inches: ";
cin >> inches;
}

void showlength()
{
cout << feet << " feet and " << inches << " inches.";
}

Operator Overloading
OVERLOADING BINARY OPERATORS

void add_length (length l1, length l2)


{
inches = l1.inches + l2.inches;
feet = l1.feet + l2.feet;

if (inches >= 12)


{
inches = inches – 12;
++feet;
}
}
};

Operator Overloading
OVERLOADING BINARY OPERATORS

The output of this program is:


main()
{ Enter Feet: 17↵
length len1, len3; Enter Inches: 5.75↵
length len2 (11, 6.25);
Length 1 = 17 feet and 5.75
inches.
len1.getlength(); Length 2 = 11 feet and 6.25
inches.
Length 3 = 29 feet and 0 inches.
len3.add_length (len1, len2);

cout << "\nLength 1 = "; len1.showlength();


cout << "\nLength 2 = "; len2.showlength();
cout << "\nLength 3 = "; len3.showlength();
}

Operator Overloading
OVERLOADING BINARY OPERATORS

• In this program, two objects of class length, len1


and len2, were added and the result is stored in
another object len3 by using the statement:

len3.add_dist(len1, len2);

• By overloading the + operator, the programmer


can reduce this dense-looking expression to:

len3 = len1 + len2;

Operator Overloading
OVERLOADING BINARY OPERATORS

• Revised Length Program (with overloaded add operator)

#include <iostream>
using namespace std;

class length
{
private:
int feet;
float inches;

public:
length () : feet (0), inches (0.0)
{}
length (int ft, float in) : feet(ft), inches(in)
{}

Operator Overloading
OVERLOADING BINARY OPERATORS

void getlength()
{
cout << "\nEnter Feet: ";
cin >> feet;
cout << "Enter Inches: ";
cin >> inches;
}

void showlength()
{
cout << feet << " feet and " << inches << " inches.";
}

Operator Overloading
OVERLOADING BINARY OPERATORS

length operator + (length l2) Here the operator+ () function


{ adds the feet data member of
int f; float i; the object l2 and this object and
stores the result to the local
f = feet + l2.feet; variable f.
i = inches + l2.inches;
It will also add the inches data
if (i >= 12) member of the object l2 and this
{ object and stores the result to
i = i - 12; the local variable i.
++f;
}
return length (f, i); It then returns a temporary
} object of class length initialized
}; with the values of f and i.

Operator Overloading
OVERLOADING BINARY OPERATORS
The output of this program is:
main()
Enter Feet: 10↵
{
Enter Inches: 6.5↵
length len1, len3, len4;
length len2 (11, 6.25);
Length 1 = 10 feet and 6.5 inches.
Length 2 = 11 feet and 6.25
len1.getlength(); inches.
Length 3 = 22 feet and 0.75
len3 = len1 + len2; inches.
len4 = len1 + len2 + len3; Length 4 = 44 feet and 1.5 inches.

cout << "\nLength 1 = "; len1.showlength();


cout << "\nLength 2 = "; len2.showlength();
cout << "\nLength 3 = "; len3.showlength();
cout << "\nLength 4 = "; len4.showlength();
}

Operator Overloading
OVERLOADING BINARY OPERATORS

• In the expression:

len3 = len1 + len2;

when the compiler sees this expression it looks at the argument


types, and finding only type length, it realizes it must use the
length member function operator +().

• The argument on the left side of the operator (len1 in this case) is
the object of which the operator is a member. The object on the
right side of the operator (len2) must be furnished as an argument
to the operator. The operator returns a value, which can be
assigned or used in other ways; in this case it is assigned to len3.

Operator Overloading
COMPARISON OVERLOADING

• Revised Length Program (with overloaded less than (<) operator)

#include <iostream>
using namespace std;

class length
{
private:
int feet;
float inches;

public:
length () : feet (0), inches (0.0)
{}
length (int ft, float in) : feet(ft), inches(in)
{}

Operator Overloading
COMPARISON OVERLOADING

void getlength()
{
cout << "\nEnter Feet: ";
cin >> feet;
cout << "Enter Inches: ";
cin >> inches;
}

void showlength()
{
cout << feet << " feet and " << inches << " inches.";
}

Operator Overloading
COMPARISON OVERLOADING

bool operator < (length l2)


{ Here the operator< () function
float f1, f2; compares the total length of
the object l2 and this object.
f1 = feet + inches/12;
f2 = l2.feet + l2.inches/12; It first converts the feet and
inches data members of both
objects (this object and the
if (f1 < f2) object l2) to a total length.
return true;
else It then compares both lengths
return false; and returns the appropriate
} result (true or false).
};

Operator Overloading
COMPARISON OVERLOADING
The output of this program is:
main() Enter Feet: 5↵
{ Enter Inches: 11.5↵
length len1;
length len2 (6, 2.5); Length 1 = 5 feet and 11.5 inches.
Length 2 = 6 feet and 2.5 inches.

len1.getlength(); Length 1 is less than Length 2.

cout << "\nLength 1 = "; len1.showlength();


cout << "\nLength 2 = "; len2.showlength();

if (len1 < len2)


cout << "\nLength 1 less than Length 2.";
else
cout << "\nLength 2 less than Length 1.";
}

Operator Overloading
DATA CONVERSION

• The assignment (=) operator will


assign a value from one variable to
another such as in statements like:

intvar1 = intvar2;

where intvar1 and intvar2 are integer


variables.
Operator Overloading
DATA CONVERSION

• The = operator also assigns the value of one user-defined


object to another, provided they are of the same type, in
statements like:

len1 = len2;

where len2, which is type length, is assigned to another


object of also type length, len3.

Normally, then the value of one object is assigned to


another of the same type, the values of all the member
data items are simply copied into the new object.

Operator Overloading
DATA CONVERSION

• In a statement like:

intvar = floatvar;

where intvar is of type int and floatvar is of


type float, it is assumed that the compiler
will call a special routine to convert the value
of floatvar, which is expressed in
floating-point format, to an integer format so
that it can be assigned to intvar.

Operator Overloading
DATA CONVERSION

• There are of course many such conversions: from float to


double, char to float, and so on. Each such conversion has
its own routine, built into the compiler and called up
when the data types on different sides of the equal sign
so dictate.

• When it is desired to convert between user-defined data


types and basic types, the programmer cannot rely on
built-in conversion routines, since the compiler does not
know anything about user-defined types. Instead,
programmers must write these routines themselves.

Operator Overloading
DATA CONVERSION

• Revised Length Program (with data conversion)

#include <iostream>
using namespace std;

class length
{
private:
int feet;
float inches;

public:
length () : feet (0), inches (0.0)
{}
length (int ft, float in) : feet(ft), inches(in)
{}

Operator Overloading
DATA CONVERSION

void getlength()
{
cout << "\nEnter Feet: ";
cin >> feet;
cout << "Enter Inches: ";
cin >> inches;
}

void showlength()
{
cout << feet << " feet and " << inches << " inches.";
}

Operator Overloading
DATA CONVERSION

To convert a basic type – float in this case – to a


user-defined type such as length, use a
constructor with one argument. These are
sometimes called conversion constructors.

length (float meters) This function is called when an object of type


{ length is created with a single argument. The
float fltfeet; function assumes that this argument represents
meters.
fltfeet = 3.821 * meters;
feet = fltfeet; It converts the argument to feet and inches, and
inches = 12 * (fltfeet - feet); assigns the resulting values to the object.
}
Thus the conversion from meters to length is
carried out along with the creation of an object
in the statement:

length len1(2.35);

Operator Overloading
DATA CONVERSION

To convert a user-defined type to a basic


type such as float, create a conversion
operator. This operator takes the value
operator float() const of the length object of which it is a
{ member, converts it to a float value
float fracfeet; representing meters, and returns this
value.
fracfeet = inches/12;
fracfeet = fracfeet + feet; This operator can be called with a simple
assignment statement:
return fracfeet/3.821;
}
mtrs = len1;
};
This converts the length object to its
equivalent float value in meters.

Operator Overloading
DATA CONVERSION

The output of this program is:


main()
{ Length 1 = 7 feet and 8.52419 inches.
float mtrs; Length 1 = 2.35 meters
length len1(2.35);
length len2(5, 10.25); Length 2 = 1.78426 meters

cout << "\nLength 1 = "; len1.showlength();


mtrs = len1;
cout << “\nLength 1 = “ << mtrs << “ meters\n”;

mtrs = len2;
cout << “\nLength 2 = “ << mtrs << “ meters\n”;
}

Operator Overloading
CONVERSION OF OBJECTS OF DIFFERENT CLASSES

• In converting between objects of different user-defined classes, the


same two methods just shown for conversions between basic types
and user-defined types also apply.

• Either use a one-argument constructor or use a conversion


operator. The choice depends on whether the programmer wants
to put the conversion routine in the class declaration of the source
object or of the destination object.

• For example, for: objecta = objectb;

where objecta is a member of class A and objectb is a member of


class B. The conversion routine can be located in class A (the
destination class, since objecta receives the value) or class B (the
source class).

Operator Overloading
CONVERSION OF OBJECTS OF DIFFERENT CLASSES

• Time Program (with conversion routine in source object)

#include <iostream>
using namespace std;

class time12
{
private:
int pm, hrs, mins;

public:
time12() : pm(1), hrs(0), mins(0)
{}

time12(int ap, int h, int m) : pm(ap), hrs(h), mins(m)


{}

Operator Overloading
CONVERSION OF OBJECTS OF DIFFERENT CLASSES

void display()
{
cout << hrs << ":";
if (mins < 10)
cout << 0;
cout << mins << " ";
if (pm == 1)
cout << "p.m.";
else
cout << "a.m.";
}
};

Operator Overloading
CONVERSION OF OBJECTS OF DIFFERENT CLASSES

class time24
{
private:
int hours, minutes, seconds;

public:
time24() : hours(0), minutes(0), seconds(0)
{}

time24(int h, int m, int s) : hours(h), minutes(m), seconds(s)


{}

Operator Overloading
CONVERSION OF OBJECTS OF DIFFERENT CLASSES

void display() const


{
if (hours < 10)
cout << 0;
cout << hours << ":";

if (minutes < 10)


cout << 0;
cout << minutes << ":";

if (seconds < 10)


cout << 0;
cout << seconds;
}

Operator Overloading
CONVERSION OF OBJECTS OF DIFFERENT CLASSES

operator time12() const


{
int hrs12, mins12, pm;
When the conversion
if (seconds < 30) routine is in the source
mins12 = minutes; class, it is commonly
implemented as a
else conversion operator.
mins12 = minutes + 1;

if (mins12 == 60)
{
mins12 = 0;
hrs12 = hours + 1;
}
else
hrs12 = hours;

Operator Overloading
CONVERSION OF OBJECTS OF DIFFERENT CLASSES

if (hrs12 >= 12)


pm = 1;
else
pm = 0;

if (hrs12 == 0 || hrs12 == 24)


{
hrs12 = 12;
pm = 0;
}

if (hrs12 > 12)


hrs12 = hrs12 - 12;

return time12(pm, hrs12, mins12);


}
};

Operator Overloading
CONVERSION OF OBJECTS OF DIFFERENT CLASSES

main()
{
int h, m, s; time12 t12;
The output of this program is:
cout << "Enter 24-hour Time\n";
cout << " Hours: "; Enter 24-hour Time
cin >> h; Hours: 23
cout << " Minutes: "; Minutes: 59
cin >> m; Seconds: 45
cout << " Seconds: "; You entered: 23:59:45
cin >> s; 12-hour Time: 12:00 a.m.
time24 t24(h, m, s);
cout << "You entered: ";
t24.display();

t12 = t24;
cout << "\n12-hour time: ";
t12.display();
}

Operator Overloading
CONVERSION OF OBJECTS OF DIFFERENT CLASSES

• Time Program (with conversion routine in destination object)

#include <iostream>
using namespace std;

class time24
{
private:
int hours, minutes, seconds;

public:
time24() : hours(0), minutes(0), seconds(0)
{}

time24(int h, int m, int s) : hours(h), minutes(m), seconds(s)


{}

Operator Overloading
CONVERSION OF OBJECTS OF DIFFERENT CLASSES

void display() const


{
if (hours < 10)
cout << 0;
cout << hours << ":";

if (minutes < 10)


cout << 0;
cout << minutes << ":";

if (seconds < 10)


cout << 0;
cout << seconds;
}

Operator Overloading
CONVERSION OF OBJECTS OF DIFFERENT CLASSES

int gethrs() const


Things are complicated by
{ return hours; } the fact that the
constructor in the
destination class must be
able to access the data in
int getmins() const the source class to
{ return minutes; } perform the conversion.

The data in time24 —


hours, minutes, and
int getsecs() const seconds — is private, so
the program must provide
{ return seconds; } special member functions
in time24 to allow direct
access to it.
};

Operator Overloading
CONVERSION OF OBJECTS OF DIFFERENT CLASSES

class time12
{
private:
int pm, hrs, mins;

public:
time12() : pm(1), hrs(0), mins(0)
{}

time12(int ap, int h, int m) : pm(ap), hrs(h), mins(m)


{}

Operator Overloading
CONVERSION OF OBJECTS OF DIFFERENT CLASSES

void display() const


{
cout << hrs << ":";

if (mins < 10)


cout << 0;
cout << mins << " ";

if (pm == 1)
cout << "p.m.";
else
cout << "a.m.";
}

Operator Overloading
CONVERSION OF OBJECTS OF DIFFERENT CLASSES

time12 (time24 t24)


{
int secs;
The conversion routine is the
secs = t24.getsecs(); one-argument constructor
if (secs < 30) from the time12 class.
mins = t24.getmins();
else This function sets the object
mins = t24.getmins() + 1;
of which it is a member to
values that correspond to
if (mins == 60)
{
the time24 values of the
mins = 0;
object received as an
hrs = t24.gethrs() + 1;
argument.
}
else
hrs = t24.gethrs();

Operator Overloading
CONVERSION OF OBJECTS OF DIFFERENT CLASSES

if (hrs >= 12)


pm = 1;
else
pm = 0;

if (hrs == 0 || hrs == 24)


{
hrs = 12;
pm = 0;
}

if (hrs > 12)


hrs = hrs - 12;
}
};

Operator Overloading
CONVERSION OF OBJECTS OF DIFFERENT CLASSES

main()
{
int h, m, s;

cout << "Enter 24-hour Time\n";


cout << " Hours: "; The output of this program is:
cin >> h;
cout << " Minutes: ";
cin >> m; Enter 24-hour Time
cout << " Seconds: "; Hours: 23
cin >> s; Minutes: 59
time24 t24(h, m, s);
cout << "You entered: "; Seconds: 45
t24.display(); You entered: 23:59:45
12-hour Time: 12:00 a.m.
time12 t12;

t12 = t24;
cout << "\n12-hour time: ";
t12.display();
}

Operator Overloading

You might also like