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

Ch08 Operator Overloading in C++

This document discusses overloading operators in C++. It begins by explaining how overloading the unary increment (++) operator allows incrementing a Counter class using ++c1 syntax rather than c1.inc_count(). It then demonstrates overloading the unary operator to return a value that can be used in assignments. The document also covers overloading the binary + operator to add two Distance objects. Overall, it provides examples of overloading unary and binary operators to make code more readable and intuitive when working with user-defined types.

Uploaded by

Musa Khan
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
29 views

Ch08 Operator Overloading in C++

This document discusses overloading operators in C++. It begins by explaining how overloading the unary increment (++) operator allows incrementing a Counter class using ++c1 syntax rather than c1.inc_count(). It then demonstrates overloading the unary operator to return a value that can be used in assignments. The document also covers overloading the binary + operator to add two Distance objects. Overall, it provides examples of overloading unary and binary operators to make code more readable and intuitive when working with user-defined types.

Uploaded by

Musa Khan
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 65

Object Oriented

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
{ }

unsigned int get_count() // return count


{ return count; }

void operator ++ (){ // increment

(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

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


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

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
};

Distance Distance::operator + (Distance d2) const


{ // add this distance to d2 and return sum
int f = feet + d2.feet; // add the feet
float i = inches + d2.inches; // add the inches
if(i >= 12.0){ // if total exceeds 12.0,
i -= 12.0; // then decrease inches by 12.0
and
f++; // increase feet by 1
} // return a temporary Distance
return Distance(f,i); // initialized to sum
}

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

// display all lengths


cout << "dist1 = " ; dist1.showdist(); cout << endl;
cout << "dist2 = " ; dist2.showdist(); cout << endl;
cout << "dist3 = " ; dist3.showdist(); cout << endl;
cout << "dist4 = " ; dist4.showdist(); cout << endl;
return 0;
}

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()

class String // user-defined string type


{
private:
enum { SZ=80 }; // we use enum for integer constants
// 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); }
21
Concatenating String (2/3)
void display() const // display the
String
{ cout << str; }
String operator + (String ss) const // add Strings
{
String temp; // make a temporary String
if( strlen(str) + strlen(ss.str) < SZ )
{
strcpy(temp.str, str); // copy this string to
temp
strcat(temp.str, ss.str); // add the argument
string
}
else{
cout << "\nString overflow"; exit(1);
}
return temp; // return temp
String
22
}
Concatenating String (3/3)
int main()
{
String s1 = "\nEid Mubarak! "; // uses constructor 2
String s2 = "Happy new year!"; // uses constructor 2
String s3; // uses constructor 1
s1.display(); cout << endl; // display strings
s2.display(); cout << endl;
s3.display(); cout << endl;
s3 = s1 + s2; // add s2 to s1,
// assign to s3
s3.display(); // display s3
cout << endl;
return 0;
}

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;

for(int j=0; j<LIMIT; j++) // insert elements


sa1.access(j) = j*10; // *left* side of equal sign

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


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

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

using namespace std;


class safearay
{
private:
int arr[LIMIT];
public:
int& operator [](int n){ // note: return by reference
if( n< 0 || n>=LIMIT ){
cout << "\nIndex out of bounds";
exit(1);
}
return arr[n];
}
}; 41
Overloaded [] Operator Returning by Reference (2/2)
int main()
{
safearay sa1;

for(int j=0; j<LIMIT; j++) // insert elements


sa1[j] = j*10; // *left* side of equal sign

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


{
int temp = sa1[j]; // *right* side of equal sign
cout << "Element " << j << " is " << temp <<
endl;
}
return 0;
}

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;
}

void showdist() const{ // display distance


cout << feet << "\'-" << inches << '\"';
}
operator float() const // conversion operator
{ // converts Distance to meters
float fracfeet = inches/12; // convert the inches
fracfeet += static_cast<float>(feet);
//add the feet
return fracfeet/MTF;
// convert to meters
}
}; 44
Conversions Between Objects and Basic Types (3/3)
int main()
{
float mtrs;
Distance dist1 = 2.35F; // uses 1-arg constructor to

// convert meters to Distance


cout << "\ndist1 = "; dist1.showdist();
mtrs = static_cast<float>(dist1);
// uses conversion operator

//for Distance to meters


cout << "\ndist1 = " << mtrs << " meters\n";
Distance dist2(5, 10.25); // uses 2-arg constructor
mtrs = dist2; // also uses conversion op

cout << "\ndist2 = " << mtrs << " meters\n";


// dist2 = mtrs; // error, = won’t convert
return 0;
}
45
Conversion Between C-Strings and String Objects (1/2)
// conversion between ordinary strings and 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 C-string
public:
String() // no-arg constructor
{ str[0] = '\0'; }
String( char s[] ) // 1-arg constructor
{ strcpy(str, s); } // convert C-string to
String
void display() const // display the String
{ cout << str; }
operator char*() // conversion operator
{ return str; } // convert String to C-string
}; 46
Conversion Between C-Strings and String Objects (2/2)
int main()
{
String s1; // use no-arg constructor
// create and initialize C-string
char xstr[] = "Joyeux Noel! ";
s1 = xstr; // use 1-arg constructor

// to convert C-string to String


s1.display(); //display String
String s2 = "Bonne Annee!"; // uses 1-arg constructor

//to initialize String


cout << static_cast<char*>(s2);
// use conversion operator

cout << endl; // to convert String to C-string

return 0; // before sending to << op


}
47
Conversions Between Objects of Different Classes (1/4)
//converts from time24 to time12 using operator in time24
#include <iostream>
#include <string>
using namespace std;
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)
{ } // no-arg constructor
time12(bool ap, int h, int m) : pm(ap), hrs(h), mins(m)
{ } // 3-arg constructor
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."; 48
Conversions Between Objects of Different Classes (2/4)
cout << am_pm;
}
};
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)
{ } // no-arg constructor
time24(int h, int m, int s) :
hours(h), minutes(m), seconds(s)
{ } // 3-arg constructor
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'; 49
Conversions Between Objects of Different Classes (3/4)
cout << seconds;
}
operator time12() const; // conversion operator
};
time24::operator time12() const // conversion operator
{
int hrs24 = hours;
bool pm = hours < 12 ? false : true; // find am/pm
//round secs
int roundMins = seconds < 30 ? minutes : minutes+1;
if(roundMins == 60) //carry mins?
{
roundMins=0;
++hrs24;
if(hrs24 == 12 || hrs24 == 24) //carry hrs?
pm = (pm==true) ? false : true; //toggle am/pm
}
int hrs12 = (hrs24 < 13) ? hrs24 : hrs24-12;
if(hrs12==0) //00 is 12 a.m.
{ hrs12=12; pm=false; } 50
Conversions Between Objects of Different Classes (4/4)
return time12(pm, hrs12, roundMins);
}
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;
time24 t24(h, m, s); //make a time24
cout << "You entered: "; //display the time24
t24.display();
time12 t12 = t24; // convert time24 to time12
cout << "\n12-hour time: "; // display equivalent time12
t12.display(); cout << "\n\n";
}
return 0; } 51
Conversions Between Objects of Different Classes (1/4)
//converts from time24 to time12 using constructor in time12
#include <iostream>
#include <string>
using namespace std;
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)
{ } //no-arg constructor
time24(int h, int m, int s) :
hours(h), minutes(m), seconds(s)
{ } // 3-arg constructor
void display() const{ // format 23:15:01
if(hours < 10) cout << '0';
cout << hours << ':';
if(minutes < 10) cout << '0';
cout << minutes << ':'; 52
Conversions Between Objects of Different Classes (2/4)
if(seconds < 10) cout << '0';
cout << seconds;
}
int getHrs() const { return hours; }
int getMins() const { return minutes; }
int getSecs() const { return seconds; }
};
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)
{ } // no-arg constructor
time12(time24); // 1-arg constructor
time12(bool ap, int h, int m) : pm(ap), hrs(h), mins(m)
{ } // 3-arg constructor
void display() const {
cout << hrs << ':'; 53
Conversions Between Objects of Different Classes (3/4)
if(mins < 10) cout << '0'; //extra zero for "01"
cout << mins << ' ';
string am_pm = pm ? "p.m." : "a.m.";
cout << am_pm;
}
};
//-------------------------------------------------------------
time12::time12( time24 t24 ) // 1-arg constructor
{ // converts time24 to time12
int hrs24 = t24.getHrs(); // get hours
pm = t24.getHrs() < 12 ? false : true; // find am/pm
mins = (t24.getSecs() < 30) ? // round secs
t24.getMins() : t24.getMins()+1;
if(mins == 60){ // carry mins ?
mins=0; ++hrs24;
if(hrs24 == 12 || hrs24 == 24) // carry hrs?
pm = (pm==true) ? false : true; // toggle am/pm
}
hrs = (hrs24 < 13) ? hrs24 : hrs24-12; //convert hrs
if(hrs==0) //00 is 12 a.m. 54
Conversions Between Objects of Different Classes (4/4)
{ hrs=12; pm=false; }
}
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) return(1); // quit if hours > 23
cout << " Minutes: "; cin >> m;
cout << " Seconds: "; cin >> s;
time24 t24(h, m, s); // make a time24
cout << "You entered: "; // display the time24
t24.display();
time12 t12 = t24; //convert time24 to time12
cout << "\n12-hour time: ";//display equivalent time12
t12.display();
cout << "\n\n";
}
return 0;} 55
Preventing Conversions with explicit (1/2)
#include <iostream>
using namespace std;
class Distance{ // English Distance class
private:
const float MTF; // meters to feet
int feet;
float inches;
public: // no-args constructor
Distance() : feet(0), inches(0.0), MTF(3.280833F)
{ }
// EXPLICIT one-arg constructor
explicit Distance(float meters) : MTF(3.280833F)
{
float fltfeet = MTF * meters;
feet = int(fltfeet);
inches = 12*(fltfeet-feet);
}
void showdist() // display distance
{ cout << feet << "\'-" << inches << '\"'; }
}; 56
Preventing Conversions with explicit (2/2)
int main(){
void fancyDist(Distance); // declaration
Distance dist1(2.35F); // uses 1-arg constructor to
// convert meters to Distance
// Distance dist2 = 2.35F; // ERROR if ctor is explicit

cout << "\ndist1 = "; dist1.showdist();


float mtrs = 3.0F;
cout << "\ndist1 ";

// fancyDist(mtrs); // ERROR if ctor is


explicit
return 0;
}
void fancyDist(Distance d){
cout << "(in feet and inches) = ";
d.showdist();
cout << endl;
}
57
Preventing Conversions with explicit

• You can call fancyDist() with arguments Distance


variable is no problem.
• you can also call fancyDist() with a variable of type float
as the argument: fancyDist(mtrs);
• The compiler will realize it’s the wrong type and look for
a conversion operator.
• Finding a Distance constructor that takes type float as an
argument, it will arrange for this constructor to convert
float to Distance and pass the Distance value to the
function.
• This is an implicit conversion, one which you may not
have intended to make possible. 58
Preventing Conversions with explicit
• However, if we make the constructor explicit, we
prevent implicit conversions.
• You can check this by removing the comment symbol
from the call to fancyDist() in the program:
• the compiler will tell you it can’t perform the
conversion. Without the explicit keyword, this call is
perfectly legal.
• As a side effect of the explicit constructor, note that you
can’t use the form of object initialization that uses an
equal sign Distance dist1 = 2.35F;
• whereas the form with parentheses works as it always
has: Distance dist1(2.35F); 59
Changing const Object Data Using mutable
• Ordinarily, when you create a const object, you want a
guarantee that none of its member data can be
changed.
• However, a situation occasionally arises where you want
to create const objects that have some specific member
data item that needs to be modified despite the object’s
constness.
• Let’s say we want to be able to create const scrollbars in
which attributes remain unchanged,
• except for their ownership. That’s where the mutable
keyword comes in.
60
Changing const Object Data Using mutable
#include <iostream>
#include <string>
using namespace std;
class scrollbar{
private:
int size; // related to constness
mutable string owner; // not relevant to constness
public:
scrollbar(int sz, string own) : size(sz), owner(own)
{ }
void setSize(int sz) // changes size
{ size = sz; }
void setOwner(string own) const // changes owner
{ owner = own; }
int getSize() const // returns size
{ return size; }
string getOwner() const // returns owner
{ return owner; }
};
61
Changing const Object Data Using mutable
int main()
{
const scrollbar sbar(60, "Window1");

// sbar.setSize(100); // can’t do this to const obj

sbar.setOwner("Window2"); // this is OK

// these are OK too

cout << sbar.getSize() << ", "


<< sbar.getOwner() << endl;
return 0;
}

62
Summary
Operators that can be overloaded
+ - * / % ^ & |
~ ! = < > += -= *=
/= %= ^= &= |= << >> >>=
<<= == != <= >= && || ++
-- ->* , -> [] () new delete
new[] delete[]

Operators that cannot be overloaded


. .* :: ?:
63
Assignment #2, Question #1
• Develop class Polynomial. The internal representation of a Polynomial is an
array of terms. Each term contains a coefficient and an exponent. The term 2x4
has the coefficient 2 and the exponent 4.
• Develop a complete class containing proper constructor and destructor
functions as well as set and get functions.
• The class should also provide the following overloaded operator capabilities:
– Overload the addition operator (+) to add two Polynomials.
– Overload the subtraction operator (-) to subtract two Polynomials.
– Overload the assignment operator to assign one Polynomial to another.
– Overload the multiplication operator (*) to multiply two Polynomials.
– Overload the addition assignment operator (+=), subtraction assignment
operator (-=), and multiplication assignment operator (*=).

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

You might also like