Ch08 Operator Overloading in C++
Ch08 Operator Overloading in C++
Programming
Chapter 08: Operator Overloading
1
Introduction
• Operator Overloading is one of the most exciting features
of object oriented programming.
• It can transform complex, obscure program listings into
intuitively obvious ones. For example,
• Statements like d3.addobjects(d1, d2); or the similar but
equally obscure d3 = d1.addobjects(d2); can be changed
to the much more readable d3 = d1 + d2;
• The rather forbidding term operator overloading refers to
giving the normal C++ operators, such as +, *, <=, and +=,
additional meanings when they are applied to user
defined data types.
2
Overloading Unary Operators
• Let’s start off by overloading a unary operator.
• Unary operators act on only one operand. (An operand is
simply a variable acted on by an operator.)
• Examples are the increment and decrement operators ++
and --, and the unary minus, as in -33.
• In Chapter 6, we created a class Counter to keep track of
a count. Objects of that class were incremented by calling
a member function: c1.inc_count();
• That did the job, but the listing would have been more
readable if we could have used the increment operator +
+ instead: ++c1;
3
Overloading Unary (++) Operator (1/2)
// countpp1.cpp increment counter variable with ++ operator
#include <iostream>
using namespace std;
class Counter{
private:
unsigned int count; // count
public:
Counter() : count(0) // constructor
{ }
(prefix)
++count;
} 4
};
Overloading Unary (++) Operator (2/2)
int main()
{
Counter c1, c2; // define and
initialize
cout << "\nc1=" << c1.get_count(); // display
cout << "\nc2=" << c2.get_count();
++c1; // increment c1
++c2; // increment c2
++c2; // increment c2
5
The operator Keyword
• The keyword operator is used to overload the ++
operator in this declarator: void operator ++ ()
• The return type (void in this case) comes first, followed
by the keyword operator, followed by the operator itself
(++), and finally the argument list enclosed in
parentheses (which are empty here).
• This declarator syntax tells the compiler to call this
member function whenever the ++ operator is
encountered, provided the operand (the variable
operated on by the ++) is of type Counter. If the operand
is a basic type such as an int, as in ++intvar; then the
compiler will use its built-in routine to increment an int.
6
Operator Arguments
• In main() the ++ operator is
applied to a specific object, as in
the expression ++c1.
• The operator++() takes no
arguments.
• It increments the count data in
the object of which it is a
member.
• Since member functions can
always access the particular
object for which they’ve been
invoked.
7
Operator Return Values
• The operator++() function in the program has a subtle
defect. You will discover it if you use a statement like this
in main(): c1 = ++c2;
• The compiler will complain. Because we have defined the
++ operator 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.
• To make it possible to use our homemade operator++() in
assignment expressions, we must provide a way for it to
return a value. The next program does that.
8
Returning Values in Operator (1/2)
//increment counter variable with ++ operator, return value
#include <iostream>
using namespace std;
class Counter{
private: unsigned int count; //count
public:
Counter() : count(0) //constructor
{ }
unsigned int get_count() //return count
{ return count; }
Counter operator ++ (){ //increment count
++count; // increment count
Counter temp; // make a temporary Counter
temp.count = count; // give it same value as
this obj
return temp; // return the copy
}
}; 9
Returning Values in Operator (2/2)
int main()
{
Counter c1, c2; // c1=0, c2=0
cout << "\nc1=" << c1.get_count(); // display
cout << "\nc2=" << c2.get_count();
++c1; // c1=1
c2 = ++c1; // c1=2, c2=2
cout << "\nc1=" << c1.get_count(); // display again
cout << "\nc2=" << c2.get_count() << endl;
return 0;
}
10
Returning Nameless Temporary Objects (1/2)
// increment with ++ operator uses unnamed temporary object
#include <iostream>
using namespace std;
class Counter{
private: unsigned int count; // count
public:
Counter() : count(0) // constructor no
args
{ }
Counter(int c) : count(c) // constructor, one arg
{ }
unsigned int get_count() // return count
{ return count; }
Counter operator ++ (){ // increment count
++count; // increment count, then
return
return Counter(count); // an unnamed temporary object
} // initialized to this count
11
};
Returning Nameless Temporary Objects (2/2)
int main()
{
Counter c1, c2; // c1=0, c2=0
cout << "\nc1=" << c1.get_count(); // display
cout << "\nc2=" << c2.get_count();
++c1; // c1=1
c2 = ++c1; // c1=2, c2=2
cout << "\nc1=" << c1.get_count(); // display again
cout << "\nc2=" << c2.get_count() << endl;
return 0;
}
12
Using Postfix Notation (1/2)
// overloaded ++ operator in both prefix and postfix
#include <iostream>
using namespace std;
class Counter{
private: unsigned int count; // count
public:
Counter() : count(0){} // constructor no args
Counter(int c) : count(c){} // constructor, one arg
unsigned int get_count() const // return count
{ return count; }
Counter operator ++ (){ // increment count (prefix)
return Counter(++count); // increment count, then
} // return an unnamed temporary
object
Counter operator ++ (int){ // increment count (postfix)
return Counter(count++); // object initialized to
this
} // count, then increment
13
count
Using Postfix Notation (2/2)
int main()
{
Counter c1, c2; // c1=0, c2=0
cout << "\nc1=" << c1.get_count(); // display
cout << "\nc2=" << c2.get_count();
++c1; // c1=1
c2 = ++c1; // c1=2, c2=2 (prefix)
cout << "\nc1=" << c1.get_count(); // display
cout << "\nc2=" << c2.get_count();
c2 = c1++; // c1=3, c2=2 (postfix)
cout << "\nc1=" << c1.get_count(); // display again
cout << "\nc2=" << c2.get_count() << endl;
return 0;
}
14
Using Postfix Notation
• In the program, We have two different declarations for
overloading the ++ operator.
• Declaration for prefix notation is Counter operator ++ ()
• for postfix notation, is Counter operator ++ (int)
• The only difference is the int in the parentheses.
• This int isn’t really an argument, and it doesn’t mean
integer.
• It’s simply a signal to the compiler to create the postfix
version of the operator.
15
Overloading Binary Operators (1/3)
// englplus.cpp overloaded ‘+’ operator adds two Distances
#include <iostream>
using namespace std;
class Distance{ // English Distance class
private: int feet; float inches;
public:
Distance() : feet(0), inches(0.0)
{} // constructor (no args)
Distance(int ft, float in) : feet(ft), inches(in)
{ } // constructor (two args)
void getdist(){ // get length from user
cout << "\nEnter feet: "; cin >> feet;
cout << "Enter inches: "; cin >> inches;
}
void showdist() const // display distance
{ cout << feet << "\'-" << inches << '\"'; }
16
Overloading Binary Operators (2/3)
Distance operator + ( Distance ) const; // add 2 distances
};
17
Overloading Binary Operators (3/3)
int main()
{
Distance dist1, dist3, dist4; // define distances
dist1.getdist(); // get dist1 from
user
Distance dist2(11, 6.25); // define, initialize dist2
dist3 = dist1 + dist2; // single ‘+’ operator
dist4 = dist1 + dist2 + dist3; // multiple ‘+’ operators
18
Overloading Binary Operators
• Binary operators ( +, -, *, /, %, =, +=, -=, *=, /=, %=) can be
overloaded just as easily as unary operators.
• In class Distance the declaration for the operator+() function
looks like this: Distance operator + ( Distance );
• This function has a return type of Distance, and takes one
argument of type Distance.
• In expressions like dist3 = dist1 + dist2; The argument on the
left side of the operator (dist1 in this case) is the object of
which the operator is a member.
• The object on the right side of the operator (dist2) 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 dist3 19
20
Concatenating String (1/3)
// strplus.cpp overloaded ‘+’ operator concatenates strings
#include <iostream>
using namespace std;
#include <string.h> // for strcpy(), strcat()
#include <stdlib.h> // for exit()
23
Enumeration
• An enumeration, introduced by the keyword enum and
followed by a type name (in our example, Status), is a set
of integer constants represented by identifiers.
• The values of these enumeration constants start at 0,
unless specified otherwise, and increment by 1.
• In the following example, the constant CONTINUE has the
value 0, WON has the value 1 and LOST has the value 2.
• enum Status { CONTINUE, WON, LOST };
• Another popular enumeration is
enum Months { JAN = 1, FEB, MAR, APR, MAY, JUN, JUL,
AUG, SEP, OCT, NOV, DEC };
24
Concatenating String
• The + operator cannot be used to concatenate C-strings.
That is, you can’t say str3 = str1 + str2;
• The program first displays three strings separately.
• The third is empty at this point, so nothing is printed
when it displays itself.
• Then the first two strings are concatenated and placed in
the third, and the third string is displayed again.
• The declarator String operator + (String ss) shows that
the + operator takes one argument of type String and
returns an object of the same type.
• The concatenation process in operator+() involves
creating a temporary object of type String, copying the25
Concatenating String
string from our own String object into it, concatenating the
argument string using the library function strcat(), and
returning the resulting temporary string.
• Note that we can’t use the return String(string); approach,
where a nameless temporary String is created,
– because we need access to the temporary String not only
to initialize it, but to concatenate the argument string to it.
• We must be careful that we don’t overflow the fixed-length
strings used in the String class. To prevent such accidents in
the operator+() function, we check that the combined length
of the two strings to be concatenated will not exceed the
maximum string length.
26
Multiple Overloading
• We’ve seen different uses of the + operator:
– to add English distances and
– to concatenate strings.
• You could put both these classes together in the same
program, and C++ would still know how to interpret the +
operator:
– It selects the correct function to carry out the
“addition” based on the type of operand.
27
Overloading Comparison (<) Operator (1/2)
// overloaded '<' operator compares two Distances
#include <iostream>
using namespace std;
class Distance{ // English Distance class
private: int feet; float inches;
public:
Distance() : feet(0), inches(0.0)
{ } // constructor (no args)
Distance(int ft, float in) : feet(ft), inches(in)
{ } // constructor (two args)
void getdist(){ // get length from user
cout << "\nEnter feet: "; cin >> feet;
cout << "Enter inches: "; cin >> inches;
}
void showdist() const // display distance
{ cout << feet << "\'-" << inches << '\"'; }
bool operator < (Distance) const; }; // compare distances
28
Overloading Comparison (<) Operator (2/2)
bool Distance::operator < (Distance d2) const{
float bf1 = feet + inches/12;
float bf2 = d2.feet + d2.inches/12;
return (bf1 < bf2) ? true : false;
}
int main(){
Distance dist1; // define Distance dist1
dist1.getdist(); // get dist1 from user
Distance dist2(6, 2.5); // define and initialize
dist2
cout << "\ndist1 = "; dist1.showdist(); // display distances
cout << "\ndist2 = "; dist2.showdist();
if( dist1 < dist2 ) // overloaded '<' operator
cout << "\ndist1 is less than dist2";
else
cout << "\ndist1 is greater than (or equal to)
dist2";
cout << endl; return 0;
29
}
Overloading Comparison (<) Operator
• The approach used in the operator < () function is similar to
overloading the + operator, except that here the operator < ()
function has a return type of bool.
• The return value is false or true, depending on the
comparison of the two distances.
• The comparison is made by converting both distances to
floating-point feet, and comparing them using the normal <
operator.
• Remember that the use of the conditional operator return
(bf1 < bf2) ? true : false; is the same as
if(bf1 < bf2) return true;
else return false;
30
Overloading Comparison (==) Operator (1/2)
// overloaded '==' operator compares strings
#include <iostream>
using namespace std;
#include <string.h> // for strcmp()
class String{ // user-defined string type
private:
enum { SZ = 80 }; // size of String objects
char str[SZ]; // holds a string
public:
String() // constructor, no args
{ strcpy(str, ""); }
String( char s[] ) // constructor, one arg
{ strcpy(str, s); }
void display() const // display a String
{ cout << str; }
void getstr() // read a string
{ cin.get(str, SZ); }
31
Overloading Comparison (==) Operator (2/2)
bool operator == (String ss) const{ // check for
equality
return ( strcmp(str, ss.str)==0 ) ? true : false; }
};
int main(){
String s1 = "yes";
String s2 = "no";
String s3;
cout << "\nEnter 'yes' or 'no': ";
s3.getstr(); // get String from user
if(s3==s1) // compare with "yes"
cout << "You typed yes\n";
else if(s3==s2) // compare with "no"
cout << "You typed no\n";
else
cout << "You didn’t follow instructions\n";
return 0;
} 32
Arithmetic Assignment (+=) Operators (1/2)
// englpleq.cpp overloaded '+=' assignment operator
#include <iostream>
using namespace std;
class Distance{ // English Distance class
private:
int feet;
float inches;
public:
Distance() : feet(0), inches(0.0)
{ } // constructor (no args)
Distance(int ft, float in) : feet(ft), inches(in)
{ } // constructor (two args)
void getdist(){ // get length from user
cout << "\nEnter feet: "; cin >> feet;
cout << "Enter inches: "; cin >> inches;
}
void showdist() const // display distance
{ cout << feet << "\'-" << inches << '\"'; }
void operator += ( Distance );
}; 33
Arithmetic Assignment (+=) Operators (2/2)
// 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) // if total exceeds 12.0,
{ // then decrease inches
inches -= 12.0; // by 12.0 and
feet++; // increase feet
} // by 1
}
int main(){
Distance dist1; // define dist1
dist1.getdist(); // get dist1 from user
cout << "\ndist1 = "; dist1.showdist();
Distance dist2(11, 6.25); // define, initialize dist2
cout << "\ndist2 = "; dist2.showdist();
dist1 += dist2; // dist1 = dist1 + dist2
cout << "\nAfter addition,";
cout << "\ndist1 = "; dist1.showdist();
cout << endl; return 0; } 34
Arithmetic Assignment (+=) Operators
• In the operator+=() function in program, the object that
takes on the value of the sum is the object of which the
function is a member.
• Thus it is feet and inches that are given values, not
temporary variables used only to return an object. The
operator+=() function has no return value; it returns type
void.
• A return value is not necessary with arithmetic
assignment operators such as +=, because the result of
the assignment operator is not assigned to anything.
• The operator is used alone, in expressions like the one in
the program. dist1 += dist2;
35
Arithmetic Assignment (+=) Operators
• If you wanted to use this operator in more complex
expressions, like dist3 = dist1 += dist2; then you would
need to provide a return value.
– You can do this by ending the operator+=() function
with a statement like return Distance(feet, inches); in
which a nameless object is initialized to the same
values as this object and returned.
36
Separate get() and put() Functions (1/2)
// creates safe array (index values are checked before access)
// uses separate put and get functions
#include <iostream>
using namespace std;
#include <process.h> // for exit()
const int LIMIT = 100;
class safearay{
private:
int arr[LIMIT];
public:
void putel(int n, int elvalue) // set value of element
{
if( n< 0 || n>=LIMIT )
{
cout << "\nIndex out of bounds"; exit(1);
}
arr[n] = elvalue;
}
37
Separate get() and put() Functions (2/2)
int getel(int n) const{ // get value of element
if( n< 0 || n>=LIMIT ){
cout << "\nIndex out of bounds"; exit(1);
}
return arr[n];
}
};
int main()
{
safearay sa1;
for(int j=0; j<LIMIT; j++) // insert elements
sa1.putel(j, j*10);
for(j=0; j<LIMIT; j++){ // display elements
int temp = sa1.getel(j);
cout << "Element " << j << " is " << temp <<
endl;
}
return 0;
} 38
Single access() Function Returning by Reference (1/2)
// uses one access() function for both put and get
#include <iostream>
using namespace std;
#include <process.h> // for exit()
const int LIMIT = 100; // array size
class safearay{
private:
int arr[LIMIT];
public:
int& access(int n) // note: return by reference
{
if( n< 0 || n>=LIMIT ){
cout << "\nIndex out of bounds"; exit(1);
}
return arr[n];
}
}; 39
Single access() Function Returning by Reference (2/2)
int main()
{
safearay sa1;
40
Overloaded [] Operator Returning by Reference (1/2)
// creates safe array (index values are checked before access)
// uses overloaded [] operator for both put and get
#include <iostream>
#include <process.h> // for exit()
const int LIMIT = 100; // array size
42
Conversions Between Objects and Basic Types (1/3)
// conversions: Distance to meters, meters to Distance
#include <iostream>
using namespace std;
class Distance{ // English Distance class
private:
const float MTF; // meters to feet
int feet;
float inches;
public: // constructor (no args)
Distance() : feet(0), inches(0.0), MTF(3.280833F)
{ } // constructor (one arg)
Distance(float meters): MTF(3.280833F){
// convert meters to Distance
float fltfeet = MTF * meters;
// convert to float feet
feet = int(fltfeet);
// feet is integer part
inches = 12*(fltfeet-feet);
// inches is what’s left
} // constructor (two args) 43
Conversions Between Objects and Basic Types (2/3)
Distance(int ft, float in) : feet(ft),
inches(in), MTF(3.280833F)
{ }
void getdist(){ // get length from user
cout << "\nEnter feet: "; cin >> feet;
cout << "Enter inches: "; cin >> inches;
}
sbar.setOwner("Window2"); // this is OK
62
Summary
Operators that can be overloaded
+ - * / % ^ & |
~ ! = < > += -= *=
/= %= ^= &= |= << >> >>=
<<= == != <= >= && || ++
-- ->* , -> [] () new delete
new[] delete[]
64
Assignment #2, Question #2
• Create a class Polar that represents the points on the plain as
polar coordinates (radius and angle).
• Create an overloaded +operator for addition of two Polar
quantities.
• “Adding” two points on the plain can be accomplished by adding
their X coordinates and then adding their Y coordinates.
• This gives the X and Y coordinates of the “answer.”
• Thus you’ll need to convert two sets of polar coordinates to
rectangular coordinates, add them, then convert the resulting
rectangular representation back to polar.
65