You are on page 1of 44

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Lecture 10

Operator Overloading
Shiow-yang Wu
Department of Computer Science and
Information Engineering
National Dong Hwa University

Operators
Operators +, -, %, ==, etc.
Really just functions!

Simply called with different syntax: x + 7


+ is binary operator with x and 7 as operands
We "like" this notation as humans

Think of it as: +(x, 7)


+ is the function name
x, 7 are the arguments
Function + returns sum of its arguments
Object-Oriented Programming in C++

Operator Overloading 2

Note1

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Operator Overloading
Built-in operators
e.g.: +, -, = , %, ==, /, *
Already work for C++ built-in types
In standard "binary" notation

We can overload them!


To work with OUR types!
To add Point types, or Money types
As appropriate for our needs
In notation were comfortable with

Always overload with similar "actions"!


Operator Overloading 3

Object-Oriented Programming in C++

Overloading Basics
Overloading operators
VERY similar to overloading functions
Operator itself is the name of function

Example: Money '+'


Money
Money

Object-Oriented Programming in C++

Money

Operator Overloading 4

Note2

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Operator Overloading

Operator overloading is a very powerful feature of


object-oriented programming. It can transform
complex, obscure program listings, such as
d3.addobjects(d1, d2);

into intuitively obvious ones as in


d3 = d1 + d2;

Operator overloading refers to giving the normal


C++ operators, such as +, *, <=, and +=,
additional meanings when they are applied to userdefined data types.

Object-Oriented Programming in C++

Operator Overloading 5

Operator Overloading

Operator overloading gives you the opportunity to


extend the C++ language into a new language of
your own design.
Data type conversion is closely connected with
operator overloading.
C++ can handle the conversion of simple type
automatically.
For user-defined types, the programmers must
define the conversion routines.
There are some pitfalls of operator overloading and
type conversion, however. They must be used with
care.

Object-Oriented Programming in C++

Operator Overloading 6

Note3

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Overloading Unary Operators


. . .
class Counter {
private:
unsigned int count;
//count
public:
Counter() : count(0)
//constructor
{ }
unsigned int get_count()
{ return count; }
void operator ++ ()
//increment (prefix)
{ ++count; }
};
Operator Overloading 7

Object-Oriented Programming in C++

Overloading Unary Operators


int main()
{
Counter c1, c2;
++c1;
++c2;
++c2;

//increment c1
//increment c2
//increment c2

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


cout << "\nc2=" << c2.get_count() << endl;
return 0;
}
Object-Oriented Programming in C++

Operator Overloading 8

Note4

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

The operator Keyword

The keyword operator is used to overload the ++


operator in the following declarator:
void operator ++ ()
This declarator tells the compiler to call this member
function whenever the ++ operator is encountered,
provided the operand is of type Counter.
If the operand is an int variable intvar, as in
++intvar;
then the normal increment operation is used.

Object-Oriented Programming in C++

Operator Overloading 9

The operator Keyword

But if the operand is a Counter variable, as in


++c1;
then the user-defined operator++() is used.
Note that operator++() takes no arguments. It
simply increments the count data in the object of
which it is a member.
For example, in the following statement
++c1;
it will increment the count data in c1.

Object-Oriented Programming in C++

Operator Overloading 10

Note5

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Operator Return Values

The operator++() function in previous example


does not allow assignment statement such as
c1 = ++c2;
To make this possible, we must provide a way for the
function to return a value.

. . .
class Counter {
private:
unsigned int count;
public:
Counter() : count(0)
{ }

//count
//constructor

Object-Oriented Programming in C++

Operator Overloading 11

Operator Return Values


unsigned int get_count()
{ return count; }
Counter operator ++ ()
//increment
{
++count;
//increment count
Counter temp; //temp Counter
temp.count = count;
return temp;
//return the copy
}
};
Object-Oriented Programming in C++

Operator Overloading 12

Note6

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Nameless Temporary Object

There are more convenient ways to return temporary


objects without giving them names.

#include <iostream>
using namespace std;
class Counter
{
private:
unsigned int count;
public:
Counter() : count(0)
{ }

//count
//constructor

Object-Oriented Programming in C++

Operator Overloading 13

Nameless Temporary Object


Counter(int c) : count(c)
{ }
int get_count()
//return count
{ return count; }
Counter operator ++ () //increment
{
++count;
//increment count
return Counter(count);
}
};

Object-Oriented Programming in C++

Operator Overloading 14

Note7

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Nameless Temporary Object


int main()
{
Counter c1, c2;

//c1=0, c2=0

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


cout << "\nc2=" << c2.get_count();
++c1;
c2 = ++c1;

//c1=1
//c1=2, c2=2

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


cout << "\nc2=" << c2.get_count() << endl;
return 0;
}

Object-Oriented Programming in C++

Operator Overloading 15

Nameless Temporary Object

Note that in order to allow statement like


return Counter(count);

we must define a one argument constructor as


in
Counter(int c) : count(c)
{ }

Object-Oriented Programming in C++

Operator Overloading 16

Note8

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Postfix Notation

The operators defined in previous examples only


allow prefix operation.
To allow postfix operation such as
c1++;

we need to define a separate operator for it.


class Counter
{
private:
unsigned int count;
public:
Counter() : count(0)
{ }
Object-Oriented Programming in C++

//count
//constructor
Operator Overloading 17

Postfix Notation
Counter(int c) : count(c)
//constructor
{ }
unsigned int get_count() const
{ return count; }
Counter operator ++ () //increment (prefix)
{ return Counter(++count); }
Counter operator ++ (int) //inc. (postfix)
{ return Counter(count++); }
};
// the (int) is NOT an argument but simply
// indicates a postfix operator
Object-Oriented Programming in C++

Operator Overloading 18

Note9

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Postfix Notation
int main()
{
Counter c1, c2;

//c1=0, c2=0

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


cout << "\nc2=" << c2.get_count();
++c1;
c2 = ++c1;

//c1=1
//c1=2, c2=2 (prefix)

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


cout << "\nc2=" << c2.get_count();
Operator Overloading 19

Object-Oriented Programming in C++

Postfix Notation
c2 = c1++;

//c1=3, c2=2 (postfix)

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


cout << "\nc2=" << c2.get_count()
<< endl;
return 0;
}

Note that the int in the parentheses is NOT


an argument. It doesnt mean integer either.
It simply indicates a postfix operator. (better
idea?)

Object-Oriented Programming in C++

Operator Overloading 20

Note10

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Overloading Arithmetic
Operators

By overloading arithmetic operator such as +, we can


reduce the obscure statement
dist3.add(dist1, dist2);

into much more natural looking expression


dist3 = dist1 + dist2;

Lets look at an example:

class Distance { //English Distance class


private:
int feet;
float inches;

Object-Oriented Programming in C++

Operator Overloading 21

Overloading Arithmetic
Operators
public:
Distance() : feet(0), inches(0.0)
{ }
Distance(int ft, float in) :
feet(ft), inches(in)
{ }
void showdist() const {
cout << feet << "\'-"
<< inches << '\"';
}
//add 2 distances
Distance operator + ( Distance ) const;
};
Object-Oriented Programming in C++

Operator Overloading 22

Note11

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Overloading Arithmetic
Operators
Distance Distance::operator + (Distance d2)
const //add Distance
{
int f = feet + d2.feet;
float i = inches + d2.inches;
if(i >= 12.0) {
i -= 12.0;
f++;
}
//return a temporary Distance
return Distance(f,i);
}

Operator Overloading 23

Object-Oriented Programming in C++

Overloading Arithmetic
Operators
int main()
{
Distance dist1(10, 6.5), dist2(11, 6.25);
Distance dist3, dist4;
dist3 = dist1 + dist2;
// '+' operator
dist4 = dist1 + dist2 + dist3;
cout << "dist1 = ";
. . .
cout << "dist4 = ";
cout << endl;
return 0;

dist1.showdist();
dist4.showdist();

}
Object-Oriented Programming in C++

Operator Overloading 24

Note12

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Overloading Arithmetic
Operators

Note that in the expression


dist3 = dist1 + dist2;
the operand on the left side of the operator (dist1)
is the object of which the operator is a member.
The object on the right side of the operator (dist2)
is an argument to the operator.
In general, an overloaded operator always requires
one less argument than its number of operands,
since one operand is the object of which the operator
is a member.

Object-Oriented Programming in C++

Operator Overloading 25

Overloading Arithmetic
Operators

This is why a unary operator requires no arguments


(such as the ++ operator we discussed earlier).
Similar functions could be created to overload other
operators in the Distance class, so that you could
substract(-), multiply(*), and divide(/) Distance
objects in natural-looking ways.

Object-Oriented Programming in C++

Operator Overloading 26

Note13

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Concatenating Strings

We can even overload the + operator for string


concatenation as in str3 = str1 + str2;

. . .
#include <string.h>
#include <stdlib.h>
class String { //user-defined string type
private:
static const int SZ = 80;
char str[SZ];
//holds a C-string
public:
String()
{ strcpy(str, ""); }
String( char s[] )
{ strcpy(str, s); }
Object-Oriented Programming in C++

Operator Overloading 27

Concatenating Strings
void display() const
{ cout << str; }
String operator + (String ss) const {
String temp; //make a temp String
if( strlen(str) + strlen(ss.str) < SZ ) {
strcpy(temp.str, str);
strcat(temp.str, ss.str);
} else {
cout << "\nString overflow";
exit(1);
}
return temp;
}
};
Object-Oriented Programming in C++

Operator Overloading 28

Note14

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Overloading Comparison
Operators
class Distance
//English Distance class
{
private:
int feet;
float inches;
public:
Distance() : feet(0), inches(0.0)
{ }
Distance(int ft, float in) :
feet(ft), inches(in)
{ }

Object-Oriented Programming in C++

Operator Overloading 29

Overloading Comparison
Operators
void getdist() {
cout << "\nEnter feet: ";
cin >> feet;
cout << "Enter inches: ";
cin >> inches;
}
void showdist() const {
cout << feet << "\'-"
<< inches << '\"';
}
//operator to compare distances
bool operator < (Distance) const;
};
Object-Oriented Programming in C++

Operator Overloading 30

Note15

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Overloading Comparison
Operators
bool Distance::operator < (Distance d2) const
//return true or false
{
float bf1 = feet + inches/12;
float bf2 = d2.feet + d2.inches/12;
return (bf1 < bf2) ? true : false;
}
int main()
{
Distance dist1;
dist1.getdist();
Operator Overloading 31

Object-Oriented Programming in C++

Overloading Comparison
Operators
Distance dist2(6, 2.5);
cout << "\ndist1 = ";
cout << "\ndist2 = ";

dist1.showdist();
dist2.showdist();

if( dist1 < dist2 ) //overloaded '<' operator


cout << "\ndist1 is less than dist2";
else
cout << "\ndist1 is >= dist2";
cout << endl;
return 0;
}
Object-Oriented Programming in C++

Operator Overloading 32

Note16

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Comparing Strings
#include <string.h>

//for strcmp()

class String
//user-defined string type
{
private:
static const int SZ = 80;
char str[SZ];
//holds a C-string
public:
String()
{ strcpy(str, ""); }
String( char s[] )
{ strcpy(str, s); }
Object-Oriented Programming in C++

Operator Overloading 33

The == Operator
void display() const
{ cout << str; }
void getstr()
{ cin.get(str, SZ); }
//operator to check for equality
bool operator == (String ss) const
{
return ( strcmp(str, ss.str)==0 ) ?
true : false;
}
};
Object-Oriented Programming in C++

Operator Overloading 34

Note17

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Arithmetic Assignment
Operators
class Distance { //English Distance class
private:
int feet;
float inches;
public:
Distance() : feet(0), inches(0.0)
{ }
Distance(int ft, float in) :
feet(ft), inches(in)
{ }
void showdist() const
{ cout << feet << "\'-"
<< inches << '\"'; }
Operator Overloading 35
Object-Oriented Programming in C++

Arithmetic Assignment
Operators
void operator += ( Distance );
};
//------ add distance to this one -------void Distance::operator += (Distance d2)
{
feet += d2.feet;
//add the feet
inches += d2.inches;
//add the inches
if(inches >= 12.0) {
inches -= 12.0;
feet++;
}
}
Object-Oriented Programming in C++

Operator Overloading 36

Note18

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

The Subscript Operator []

In C++, even the subscript operator [] can be


overloaded. This is useful when you want to do
something similar to arrays but in a different way.
For example, we could modify the way arrays are
accessed in C++ by doing bound checking on each
access.
For the overloaded subscript operator [] to be
useful, it must return by reference such that it can
be placed at the left side of equal sign.

Object-Oriented Programming in C++

Operator Overloading 37

The Subscript Operator []

We will discuss three different ways of accessing


array elements:
separate member functions putel() and
getel()
a single member function access() using return
by reference
the overloaded [] operator using return by
reference
All three programs check to ensure that all array
accesses are within bounds.

Object-Oriented Programming in C++

Operator Overloading 38

Note19

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

getel() and putel()


. . .
#include <stdlib.h>
// for exit()
const int LIMIT = 100;
//////////////////////////////////////////
class safearay1
{
private:
int arr[LIMIT];
public:
//set value of element
void putel(int n, int elvalue) {
if( n < 0 || n >= LIMIT ) {
Object-Oriented Programming in C++

Operator Overloading 39

getel() and putel()


cout << "\nIndex out of bounds";
exit(1); }
arr[n] = elvalue;
}
//get value of element
int getel(int n) const {
if( n < 0 || n >= LIMIT ) {
cout << "\nIndex out of bounds";
exit(1); }
return arr[n];
}
};
Object-Oriented Programming in C++

Operator Overloading 40

Note20

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

getel() and putel()


int main()
{
safearay1 sa1;
for(int j=0; j<LIMIT; j++)
sa1.putel(j, j*10);
for(int j=0; j<LIMIT; j++) {
// display
int temp = sa1.getel(j);
cout << "Element " << j << " is "
<< temp << endl;
}
return 0;
}

Object-Oriented Programming in C++

Operator Overloading 41

getel() and putel()

Note that the getel() and putel()


member functions are used in exactly the
same way as normal member functions.
They indeed provide a safe array
implementation.
However, the format is a bit crude.

Object-Oriented Programming in C++

Operator Overloading 42

Note21

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Single access() Function

By using the technique of return by reference, we


can use the same member function both to put and
get elements from an array.

#include <iostream>
using namespace std;
#include <stdlib.h>
//for exit()
const int LIMIT = 100;
//array size
//////////////////////////////////////////
class safearay2
{
private:
int arr[LIMIT];
Object-Oriented Programming in C++

Operator Overloading 43

Single access() Function


public:
//return by reference !
int& access(int n)
{
if( n < 0 || n >= LIMIT ) {
cout << "\nIndex out of bounds";
exit(1);
}
return arr[n];
}
};
Object-Oriented Programming in C++

Operator Overloading 44

Note22

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Single access() Function


int main()
{
safearay2 sa1;
for(int j=0; j<LIMIT; j++)
sa1.access(j) = j*10;

//left side

for(int j=0; j<LIMIT; j++) { //display


int temp = sa1.access(j); //right side
cout << "Element " << j << " is "
<< temp << endl;
}
return 0;
}

Object-Oriented Programming in C++

Operator Overloading 45

Single access() Function

Keep in mind that a function returning by reference


can be used at both sides of the equal sign.
In fact, this is one of the most common use of the
return by reference technique.
This is not good enough either. We can use the
overloaded [] operator to make things even better.

Object-Oriented Programming in C++

Operator Overloading 46

Note23

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Overloaded [] Operator
#include <iostream>
using namespace std;
#include <stdlib.h>
//for exit()
const int LIMIT = 100;
//array size
//////////////////////////////////////////
class safearay
{
private:
int arr[LIMIT];
public:
int& operator [](int n) //return by reference
{
Object-Oriented Programming in C++

Operator Overloading 47

Overloaded [] Operator
if( n < 0 || n >= LIMIT ) {
cout << "\nIndex out of bounds";
exit(1);
}
return arr[n];
}
};

Note that the overloaded [] operator must


return by reference since the subscript
operator is commonly used on the left side of
the equal sign.

Object-Oriented Programming in C++

Operator Overloading 48

Note24

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Overloaded [] Operator
int main()
{
safearay sa1;
for(int j=0; j<LIMIT; j++)
sa1[j] = j*10;
//*left* side
for(int j=0; j<LIMIT; j++) {
int temp = sa1[j];
//*right* side
cout << "Element " << j << " is "
<< temp << endl;
}
return 0;
}

Object-Oriented Programming in C++

Operator Overloading 49

Overloaded [] Operator

Now that the new safearay can be used exactly


like normal arrays except that they are much safer
(with bound checking on each access).
This is a good example of how you can use operator
overloading to extend the C++ language in the way
you want it to be.
This offers great flexibility and expressive power to
system designers and programmers.

Object-Oriented Programming in C++

Operator Overloading 50

Note25

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Data Conversion

When the value of one object is assigned to another


of the same type, such as
dist3 = dist1 + dist2;

the values of all the member data items are simply


copied into the new object. The compiler knows how
to do this automatically.
Data conversion occurs when one type of data is
assigned to another of different type.
The conversion can be implicit (i.e. not apparent in
the code listing) such as
intvar = floatvar;

Object-Oriented Programming in C++

Operator Overloading 51

Data Conversion

Casting provides explicit conversion:


intvar = static_cast<int>(floatvar);

For conversion of user-defined types, the


programmers must define the conversion routines.
Data conversion may seem unnecessarily complex or
even dangerous.
However, the flexibility of provided by allowing
conversions outweighs the dangers.

Object-Oriented Programming in C++

Operator Overloading 52

Note26

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Objects Basic Types


#include <iostream>
using namespace std;
//////////////////////////////////////////
class Distance { //English Distance class
private:
const float MTF;
//meters to feet
int feet;
float inches;
public:
Distance() : feet(0), inches(0.0),
MTF(3.280833F)
{ }
Object-Oriented Programming in C++

Operator Overloading 53

Objects Basic Types


Distance(float meters) : MTF(3.280833F)
{ //the conversion constructor
//convert meters to Distance
float fltfeet = MTF * meters;
feet = int(fltfeet);
inches = 12*(fltfeet-feet);
}
Distance(int ft, float in) :
feet(ft), inches(in), MTF(3.280833F)
{ }
Object-Oriented Programming in C++

Operator Overloading 54

Note27

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Objects Basic Types


void getdist() //get length from user
{
cout << "\nEnter feet: ";
cin >> feet;
cout << "Enter inches: ";
cin >> inches;
}
void showdist() const
//display
{ cout << feet << "\'-
<< inches << '\"'; }

Object-Oriented Programming in C++

Operator Overloading 55

Objects Basic Types


operator float() const
{ //the conversion operator or cast operator
//converts Distance to meters
float fracfeet = inches/12;
fracfeet += static_cast<float>(feet);
return fracfeet/MTF;
}
};

The conversion operator can be called explicitly:


mtrs = static_cast<float>(dist1);

or with a single assignment:

mtrs = dist2;
Must be a non-static member function w/o return type.

Object-Oriented Programming in C++

Operator Overloading 56

Note28

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Objects Basic Types


int main()
{
float mtrs;
//use 1-arg conversion constructor to convert
//meters to Distance
Distance dist1 = 2.35F;
cout << "\ndist1 = "; dist1.showdist();
//use conversion operator from
//Distance to meters
mtrs = static_cast<float>(dist1);
cout << "\ndist1 = " << mtrs << " meters\n";
Object-Oriented Programming in C++

Operator Overloading 57

Objects Basic Types


//uses 2-arg constructor
Distance dist2(5, 10.25);
mtrs = dist2; //uses conversion op
cout << "\ndist2 = " << mtrs
<< " meters\n";
//dist2 = mtrs; //error! = won't convert
return 0;
}

Object-Oriented Programming in C++

Operator Overloading 58

Note29

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

C-Strings String Objects


// strconv.cpp
// ordinary strings <--> class String
#include <iostream>
using namespace std;
#include <string.h>
//for strcpy(), etc.
//////////////////////////////////////////
class String
//user-defined string type
{
private:
enum { SZ = 80 }; //size of all String objects
char str[SZ];
//holds a string
Object-Oriented Programming in C++

Operator Overloading 59

C-Strings String Objects


public:
String()
{ str[0] = '\0'; }
String( char s[] )
{ strcpy(str, s); }
void display() const
{ cout << str; }
operator char*()
{ return str; }

//no-arg constructor
//1-arg constructor
//C-string -> String
//display the String
//conversion operator
//String -> C-string

};

Object-Oriented Programming in C++

Operator Overloading 60

Note30

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

C-Strings String Objects


int main()
{
String s1;

//use no-arg constructor


//create and initialize C-string
char xstr[] = "Joyeux Noel! ";
s1 = xstr;
s1.display();

//use 1-arg constructor


//to convert C-string to String
//display String

//uses 1-arg constructor to initialize String


String s2 = "Bonne Annee!";
Object-Oriented Programming in C++

Operator Overloading 61

C-Strings String Objects


//use conversion operator to convert String to
//C-string before sending to << op
cout << static_cast<char*>(s2);
cout << endl;
return 0;
}

Note that we cant use an explicit assignment


statement to convert a String to a C-string:
xstr = s2;

since the C-string xstr is an array.


Object-Oriented Programming in C++

Operator Overloading 62

Note31

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Conversions Between
Different Classes

For conversions between objects of different classes,


use the one-argument constructor or a conversion
operator depending on where we want to place our
conversion routine.
Consider the statement:
objecta = objectb;

where objecta and objectb are members of class A


and B, respectively.

If we want to place the conversion routine in the source


class (B), then a conversion operator is commonly used.
If we want to place the conversion routine in the
destination class (A), then a one-argument constructor is
commonly used.
Operator Overloading 63

Object-Oriented Programming in C++

Conversions Between
Different Classes

Lets use the conversion between two kinds of time


as an example.
12-hour Time

24-hour Time

12:00 a.m.
6:00 a.m.
12:00 p.m.
6:00 p.m.
11:59 p.m.

00:00:00
06:00:00
12:00:00
18:00:00
23:59:00

Object-Oriented Programming in C++

Operator Overloading 64

Note32

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Routine in Source Class


#include <iostream>
#include <string>
using namespace std;
class time12
{
private:
bool pm;
//true
int hrs;
//1 to
int mins;
//0 to
public:
time12() : pm(true),
{ }

= pm, false = am
12
59, no seconds !!
hrs(0), mins(0)

Object-Oriented Programming in C++

Operator Overloading 65

Routine in Source Class


time12(bool ap, int h, int m) :
pm(ap), hrs(h), mins(m)
{ }
void display() const { //format: 11:59 p.m.
cout << hrs << ':';
if (mins < 10)
cout << '0';
//extra zero for "01
cout << mins << ' ';
string am_pm = pm ? "p.m." : "a.m.";
cout << am_pm;
}
};
Object-Oriented Programming in C++

Operator Overloading 66

Note33

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Routine in Source Class


class time24
{
private:
int hours;
//0 to 23
int minutes;
//0 to 59
int seconds;
//0 to 59
public:
time24() : hours(0), minutes(0), seconds(0)
{ }
time24(int h, int m, int s) :
hours(h), minutes(m), seconds(s)
{ }
Object-Oriented Programming in C++

Operator Overloading 67

Routine in Source Class


void display() const
//format: 23:15:01
{
if (hours < 10)
cout << '0';
cout << hours << ':';
if (minutes < 10) cout << '0';
cout << minutes << ':';
if (seconds < 10) cout << '0';
cout << seconds;
}
operator time12() const; //conversion operator
};
Object-Oriented Programming in C++

Operator Overloading 68

Note34

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Routine in Source Class


time24::operator time12() const
//conversion operator
{
int hrs24 = hours;
//find am/pm
bool pm = hours < 12 ? false : true;
//round secs
int roundMins = seconds < 30 ? minutes :
minutes+1;

Object-Oriented Programming in C++

Operator Overloading 69

Routine in Source Class


if (roundMins == 60)
//carry mins?
{
roundMins=0;
++hrs24;
if (hrs24 == 12 || hrs24 == 24)
pm = (pm==true) ? false : true;
}
int hrs12 = (hrs24 < 13) ? hrs24 : hrs24-12;
if (hrs12==0)
//00 is 12 a.m.
{ hrs12=12; pm=false; }
return time12(pm, hrs12, roundMins);
}
Object-Oriented Programming in C++

Operator Overloading 70

Note35

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Routine in Source Class


int main()
{
int h, m, s;
while(true)
{
//get 24-hr time from user
cout << "Enter 24-hour time: \n";
cout << "Hours (0 to 23): "; cin >> h;
if (h > 23)
//quit if hours > 23
return(1);
cout << "
Minutes: "; cin >> m;
cout << "
Seconds: "; cin >> s;
Operator Overloading 71

Object-Oriented Programming in C++

Routine in Source Class


time24 t24(h, m, s);
//make a time24
cout << "You entered: "; //display
t24.display();
time12 t12 = t24; //convert time24 to time12
cout << "\n12-hour time: ";
t12.display();
cout << "\n\n";
}
return 0;

//display

}
Object-Oriented Programming in C++

Operator Overloading 72

Note36

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Routine in Destination Class


. . .
class time24 {
private:
int hours;
//0 to 23
int minutes;
//0 to 59
int seconds;
//0 to 59
public:
time24() : hours(0), minutes(0), seconds(0)
{ }
time24(int h, int m, int s) :
hours(h), minutes(m), seconds(s)
{ }
Object-Oriented Programming in C++

Operator Overloading 73

Routine in Destination Class


void display() const { //format 23:15:01
if (hours < 10)
cout << '0';
cout << hours << ':';
if (minutes < 10) cout << '0';
cout << minutes << ':';
if (seconds < 10) cout << '0';
cout << seconds;
}
int getHrs() const { return hours; }
int getMins() const { return minutes; }
int getSecs() const { return seconds; }
};
Object-Oriented Programming in C++

Operator Overloading 74

Note37

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Routine in Destination Class


class time12
{
private:
bool pm;
//true = pm, false = am
int hrs;
//1 to 12
int mins;
//0 to 59
public:
time12() : pm(true), hrs(0), mins(0)
{ }
time12(time24);
//1-arg constructor

Object-Oriented Programming in C++

Operator Overloading 75

Routine in Destination Class


time12(bool ap, int h, int m) : //3-arg
pm(ap), hrs(h), mins(m)
{ }
void display() const
{
cout << hrs << ':';
if (mins < 10) cout << '0';
cout << mins << ' ';
string am_pm = pm ? "p.m." : "a.m.";
cout << am_pm;
}
};
Object-Oriented Programming in C++

Operator Overloading 76

Note38

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Routine in Destination Class


time12::time12( time24 t24 )
{
//converts time24 to time12
int hrs24 = t24.getHrs();
//get hours
//find am/pm
pm = t24.getHrs() < 12 ? false : true;
//round secs
mins = (t24.getSecs() < 30) ?
t24.getMins() : t24.getMins()+1;

Object-Oriented Programming in C++

Operator Overloading 77

Routine in Destination Class


if (mins == 60) //carry mins?
{
mins = 0;
++hrs24;
if (hrs24 == 12 || hrs24 == 24)
pm = (pm == true) ? false : true;
}
hrs = (hrs24 < 13) ? hrs24 : hrs24-12;
if (hrs == 0)
//00 is 12 a.m.
{ hrs = 12;
pm = false; }
}
Object-Oriented Programming in C++

Operator Overloading 78

Note39

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Routine in Destination Class


int main()
{
int h, m, s;
while(true)
{ //get 24-hour time from user
cout << "Enter 24-hour time: \n";
cout << "Hours (0 to 23): "; cin >> h;
if (h > 23) //quit if hours > 23
return(1);
cout << "Minutes: "; cin >> m;
cout << "Seconds: "; cin >> s;
Operator Overloading 79

Object-Oriented Programming in C++

Routine in Destination Class


time24 t24(h, m, s);
//make a time24
cout << "You entered: "; //display it
t24.display();
time12 t12 = t24;

//convert time24 to time12

cout << "\n12-hour time: "; //display


t12.display();
cout << "\n\n";
}
return 0;
}
Object-Oriented Programming in C++

Operator Overloading 80

Note40

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Other Overloads

&&, ||, and comma operator

Predefined versions work for bool types


Recall: use "short-circuit evaluation"
When overloaded no longer uses
short-circuit

Uses "complete evaluation" instead


Contrary to expectations

Generally should not overload


these operators

Object-Oriented Programming in C++

Operator Overloading 81

Pitfalls of Op Overloading
and Conversion

Operator overloading and type conversions give you


the power to extend the C++ language and to make
your program listing more intuitive.
They can make your listing more obscure and hard to
understand too, it not used properly.
Guidelines:

Use similar meanings


Use similar syntax
Show restraint (too much of a good thing is bad)
Avoid ambiguity (avoid doing the same conversion in more
than one way)

Object-Oriented Programming in C++

Operator Overloading 82

Note41

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Pitfalls of Op Overloading
and Conversion

Note that you cant overload a binary operator to be


a unary operator, or vice versa.
The following operators cannot be overloaded:

dot operator (.)


scope resolution operator (::)
conditional operator (?:)
pointer-to-member operator (->)

You cant create new operator (like *&) and try to


overload them; only existing operators can be
overloaded.

Object-Oriented Programming in C++

Operator Overloading 83

Assignment 7
1.

A complex ("imaginary") number has the form a + bi, where i


is the square root of -1. Here, a is called the real part and b
is called the imaginary part. Alternatively, a + bi can be
expressed as the ordered pair of real numbers (a, b).
Arithmetic operations on two complex numbers (a, b) and (c,
d) are as follows:
(a, b) + (c, d) = (a + c, b + d)
(a, b) - (c, d) = (a - c, b - d)
(a, b) * (c, d) = (a*c - b*d, a*d + b*c)
(a, b) / (c, d) = ((a*c + b*d)/(c2 + d2), (b*c - a*d)/(c2 + d2))
Also, the absolute value (or magnitude) of a complex number
is defined as
| (a, b) | = sqrt(a2 + b2)

Object-Oriented Programming in C++

Operator Overloading 84

Note42

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Assignment 7
Design, implement, and test a complex number
class that represents the real and imaginary parts as
double precision values (data type double) and
provides at least the following operations:

constructors for explicit as well as default


initialization. The default initial value should be (0.0, 0.0).
arithmetic operations that add, subtract, multiply, and
divide two complex numbers. These should be
implemented as value-returning functions, each returning
a class object.
a complex absolute value operation as a value-return
function
two accessor functions, RealPart and ImagPart, that
return the real and imaginary parts of a complex number.

Object-Oriented Programming in C++

Operator Overloading 85

Assignment 7
2.

Modify your complex number class designed above


by overloading the arithmetic operators (+, -, *, /)
to work on complex numbers. In addition to the
arithmetic operators, also overload the equals (==),
not equal (!=), and unary minus (-) for the complex
number class. Note that complex numbers x = a +
bi and y = c + di are equal if and only if a equals c
and b equals d. If x = a + bi is a complex number,
-x equals -a - bi.

Object-Oriented Programming in C++

Operator Overloading 86

Note43

CSIEB0040 Object-Oriented Programming in C++

Lecture10 Operator Overloading

Assignment 7
3.

Augment the safearay class discussed in the class


so that the user can specify both the upper and
lower bound of the array (indexes running from 100
to 200, for example). Have the overloaded subscript
operator check the index each time the array is
accessed to ensure it is not out of bounds. You'll
need to add a two-argument constructor that
specifies the upper and lower bounds. Since we
have not yet learned how to allocate memory
dynamically, the member data will still be an array
that starts at 0 and runs up to 99, but perhaps you
can map the indexes for the safearay into different
indexes in the real int array. For example, if the
client selects a range from 100 to 175, you could
map this into the range from arr[0] to arr[75].

Object-Oriented Programming in C++

Operator Overloading 87

Assignment 7
4.

Modify your Polynomial class in assignment 6 by


providing the following overloaded operators:

Addition operator (+) to add two Polynomials


Subtraction operator (-) to subtract two Polynomials
Assignment operator (=) to assign one Polynomial to
another
Multiplication operator (*) to multiply two Polynomials
Addition assignment operator (+=), the subtraction
assignment operator (-=), and the multiplication
assignment operator (*=)

(Write test programs for all your classes.)


Due: May 28, 2012
Object-Oriented Programming in C++

Operator Overloading 88

Note44

You might also like