Lecture11 PDF
Lecture11 PDF
Lecture11 PDF
11
Operator
Overloading;
String and Array
Objects
2008 Pearson Education, Inc. All rights reserved.
OBJECTIVES
In this chapter youll learn:
What operator overloading is and how it makes programs more
readable and programming more convenient.
To redefine (overload) operators to work with objects of userdefined classes.
The differences between overloading unary and binary
operators.
To convert objects from one class to another class.
When to, and when not to, overload operators.
To create PhoneNumber, Array, String and Date classes
that demonstrate operator overloading.
To use overloaded operators and other member functions of
standard library class string.
To use keyword explicit to prevent the compiler from using
single-argument constructors to perform implicit conversions.
2008 Pearson Education, Inc. All rights reserved.
11.1
11.2
11.3
11.4
11.5
11.6
11.7
11.8
11.9
11.10
11.11
11.12
11.13
11.14
11.15
Introduction
Fundamentals of Operator Overloading
Restrictions on Operator Overloading
Operator Functions as Class Members vs. Global Functions
Overloading Stream Insertion and Stream Extraction
Operators
Overloading Unary Operators
Overloading Binary Operators
Case Study: Array Class
Converting between Types
Case Study: String Class
Overloading ++ and -Case Study: A Date Class
Standard Library Class string
explicit Constructors
Wrap-Up
11.1 Introduction
Use operators with objects (operator overloading)
Clearer than function calls for certain classes
Operator sensitive to context
Examples
<<
Stream insertion, bitwise left-shift
+
Performs arithmetic on multiple items (integers, floats, etc.)
Overloading operators
Create a function for the class
Name of operator function
Keyword operator followed by symbol
Example
operator+ for the addition operator +
vs.
10
Cannot change
Precedence of operator (order of evaluation)
Use parentheses to force order of operators
11
12
*
=
/
<
%
>
^
+=
&
-=
|
*=
/=
%=
^=
&=
|=
<<
>>
>>=
<<=
==
!=
<=
>=
&&
||
++
--
->*
->
[]
()
new
delete
new[]
new[]
delete[]
delete[]
13
.*
::
?:
14
15
16
17
18
19
Operator functions
As member functions
Leftmost object must be of same class as operator function
Use this keyword to implicitly get left operand argument
Operators (),
() [],
[] -> or any assignment operator must be
overloaded as a class member function
Called when
Left operand of binary operator is of this class
Single operand of unary operator is of this class
As global functions
Need parameters for both operands
Can have object of different class than operator
Can be a friend to access private or protected data
2008 Pearson Education, Inc. All rights reserved.
20
21
22
Commutative operators
May want + to be commutative
So both a
a + b
b + a
b and b
a work
23
<<
<< and >> operators
Already overloaded to process each built-in type
Can also process a user-defined class
Overload using global, friend functions
Example program
Class PhoneNumber
Holds a telephone number
#ifndef PHONENUMBER_H
#define PHONENUMBER_H
Outline
24
5
6
#include <iostream>
using std::ostream;
using std::istream;
PhoneNumber.h
(1 of 1)
9
10 #include <string>
11 using std::string;
12
13 class PhoneNumber
14 {
15
16
17 private:
private:
18
19
20
#include <iomanip>
using std::setw;
6
7
#include "PhoneNumber.h"
8
9
Outline
25
15
16
18
19 // overloaded stream extraction operator; cannot be
20 // a member function if we would like to invoke it with
Outline
26
input.ignore(); // skip (
25
26
27
28
29
30
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
Outline
fig11_05.cpp
(1 of 2)
8
9
27
#include "PhoneNumber.h"
"PhoneNumber.h"
10
11 int main()
12 {
13
14
15
cout << "Enter phone number in the form (123) 456456-7890:" << endl;
16
17
18
19
20
21
22
23
24
// the global
global function call operator<<( cout, phone )
25
26
return 0;
27 } // end main
Outline
28
fig11_05.cpp
(2 of 2)
29
30
31
32
};
!s becomes s.operator
s.operator!()
operator!()
If global function, needs one argument
bool operator!(
operator!( const String & )
s! becomes operator!(s
operator!(s)
!(s)
2008 Pearson Education, Inc. All rights reserved.
33
34
};
y += z becomes y.operator
operator+=( z )
y.operator+=(
35
No range checking
Cannot be compared meaningfully with ==
No array assignment (array names are const pointers)
If array passed to a function, size must be passed as a separate
argument
Range checking
Array assignment
Arrays that know their own size
Outputting/inputting entire arrays with << and >>
Array comparisons with == and !=
36
#ifndef ARRAY_H
#define ARRAY_H
Outline
37
5
6
#include <iostream>
using std::ostream;
using std::istream;
Array.h
(1 of 2)
9
10 class Array
11 {
12
13
14 public:
public:
15
16
17
~Array(); // destructor
18
19
20
21
bool operator==(
operator==( const Array & ) const;
const; // equality operator
22
23
24
bool operator!=(
operator!=( const Array &right ) const
25
26
27
return ! ( *this
*this == right ); // invokes Array::operator==
} // end function operator!=
operator!=
28
29
30
int &operator
&operator[](
operator[]( int );
Outline
38
31
32
33
int operator[](
operator[]( int ) const;
const;
Array.h
34 private:
private:
35
36
(2 ofspecific
2)
Operators for accessing
array elements of Array object
#include <iostream>
using std::cerr;
using std::cout;
using std::cin;
using std::endl;
Array.cpp
(1 of 6)
8
9
Outline
39
#include <iomanip>
10 using std::setw;
11
12 #include <cstdlib>
<cstdlib> // exit function prototype
13 using std::exit;
14
15 #include "Array.h" // Array class definition
16
17 // default constructor for class Array (default size 10)
18 Array::Array( int arraySize )
19 {
20
21
22
23
24
26
Outline
40
: size( arrayToCopy.size )
Array.cpp
31 {
32
(2 of 6)
33
34
35
39 Array::~Array()
40 {
41
42 } // end destructor
43
44 // return number of elements of Array
45 int Array::getSize() const
46 {
47
49
50 // overloaded assignment operator;
Outline
41
55
56
57
58
if ( size != right.size )
59
60
61
62
63
Array.cpp
(3 of 6)
Want to avoid self assignment
This would be dangerous if this
is the same Array as right
} // end inner if
64
65
66
67
68
69
71
72 // determine if two Arrays are equal and
73 // return true, otherwise return false
74 bool Array::
Array::operator
operator==(
operator
==( const Array &right ) const
75 {
Outline
76
77
78
if ( size != right.size )
return false;
false; // arrays of different number of elements
elements
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
42
Array.cpp
(4 of 6)
return true;
true; // Arrays are equal
} // end function operator==
// overlo
overloaded
aded subscript operator for nonnon-const Arrays;
// reference return creates a modifiable lvalue
int &Array::operator
&Array::operator[](
operator[]( int subscript )
{
// check for subscript outout-ofof-range error
if ( subscript < 0 || subscript >= size )
{
integers1[ 5 ] calls
integers1.operator[]( 5 )
97
98
return ptr[ subscript ]; // reference return
99 } // end function operator[]
100
101 // overloaded subscript operator for const Arrays
102 // const reference return creates an rvalue
Outline
43
106
107
108
109
110
111
Array.cpp
(5 of 6)
cerr << "\nError: Subscript " << subscript
<< " out of range" << endl;
exit( 1 ); // terminate program; subscript out of range
} // end if
112
113
122
123
125
126 // overloaded output operator for class Array
127 ostream &operator
&operator<<(
operator<<( ostream &output, const Array &a )
Outline
44
128 {
129
int i;
Array.cpp
130
131
132
133
134
(6 of 6)
135
136
137
138
139
140
141
142
143
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
fig11_08.cpp
#include "Array.h"
(1 of 5)
Outline
45
7
8
9
10 int main()
11 {
12
13
14
15
16
17
<< integers1.getSize()
18
19
20
21
22
<< integers2.getSize()
23
<< "\
"\nArray after initialization:\
initialization:\n" << integers2;
24
25
26
27
28
29
30
<< "integers1:\
"integers1:\n" << integers1
31
<< "integers2:\
"integers2:\n" << integers2;
integers2;
Outline
46
32
33
34
fig11_08.cpp
35
36
37
if ( integers1 != integers2 )
cout << "integers1 and integers2 are not equal" << endl;
38
39
40
41
42
43
44
<< integers3.getSize()
45
46
47
48
49
50
51
52
53
54
55
56
57
58
if ( integers1 == integers2 )
47
59
60
61
fig11_08.cpp
63
// use overloaded
overloaded subscript operator to create lvalue
(3 of 5)
64
65
integers1[ 5 ] = 1000;
1000;
66
62
67
68
69
70
71
return 0;
72 } // end main
Outline
0
0
48
fig11_08.cpp
0
0
0
0
3
7
10
14
11
15
(4 of 5)
Enter 17 integers:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
After input, the Arrays contain:
integers1:
1
2
5
6
integers2:
8
9
12
13
16
17
Outline
3
7
49
fig11_08.cpp
10
14
11
15
10
14
11
15
(5 of 5)
10
14
11
15
50
51
52
53
54
55
56
57
Must be non-static
static member function
Do not specify return type
Implicitly returns type to which you are converting
58
59
60
Conversion constructor
Any single-argument constructor
Turns objects of other types into class objects
Example
String s1( "happy" );
Creates a String from a char *
#ifndef STRING_H
#define STRING_H
Outline
61
5
6
#include <iostream>
using std::ostream;
using std::istream;
9
10 class String
String.h
(1 of 3)
Conversion constructor to make
a String from a char *
11 {
12
13
14 public:
public:
15
16
17
~String(); // destructor
destructor
18
s1 += s2 will be interpreted
as s1.operator+=(s2)
19
20
21
22
bool operator!()
operator!() const;
const; // is String
String empty?
23
bool
24
bool
25
26
// test s1 != s2
27
bool operator!=(
operator!=( const String &right ) const
28
{
return !( *this
*this == right );
29
30
Outline
62
31
String.h
32
// test s1 > s2
33
bool operator>(
operator>( const String &right ) const
34
35
36
37
38
// test s1 <= s2
39
bool operator<=(
operator<=( const String &right ) const
40
41
42
} // end function
function operator <=
(2 of 3)
Overload equality and
relational operators
43
44
// test s1 >= s2
45
bool operator>=(
operator>=( const String &right ) const
46
47
48
return !( *this
*this < right );
} // end function operator>=
49
50
char &operator
&operator[](
operator[]( int ); // subscript operator (modifiable lvalue)
51
char operator[](
operator[]( int ) const;
const; // subscript operator (rvalue)
52
String operator()(
operator()( int,
int, int = 0 ) const; // return a substring
53
54 private:
private:
55
56
57
58
Outline
63
#include <iostream>
using std::cerr;
using std::cout;
using std::endl;
String.cpp
#include <iomanip>
(1 of 7)
using std::setw;
Outline
64
10
11 #include <cstring> // strcpy
strcpy and strcat prototypes
12 using std::strcmp;
13 using std::strcpy;
14 using std::strcat;
15
16 #include <cstdlib> // exit prototype
17 using std::exit;
18
19 #include "String.h" // String class definition
20
21 // conversion (and default)
default) constructor converts char * to String
22 String::String( const char *s )
23
: length( ( s != 0 ) ? strlen( s ) : 0 )
24 {
25
cout << "Conversion (and default) constructor: " << s << endl;
26
29 // copy constructor
30 String::String( const String © )
31
: length( copy.length )
Outline
65
32 {
33
34
String.cpp
(2 of 7)
37 // Destructor
38 String::~String()
39 {
40
41
48
49
50
51
52
53
54
} // end if
55
else
56
57
return *this
*this;
this; // enables cascaded assignments
59 } // end function operator=
60
58
size_t newLength
newLength = length + right.length; // new length
char *tempPtr = new char[
char[ newLength + 1 ]; // create memory
66
67
68
Outline
66
String.cpp
(3 of 7)
69
70
71
72
73
delete [] sPtr;
sPtr; // reclaim old space
sPtr = tempPtr; // assign new array to sPtr
length = newLength; // assign new length to length
*this
this;
return *
this
; // enables cascaded calls
Outline
67
91
String.cpp
(4 of 7)
104
return sPtr[ subscript ]; // nonnon-const return; modifiable lvalue
106 } // end function operator[]
107
105
118
119
Outline
68
121
122 // return a substring beginning at index and of length subLength
123 String String::operator()( int index, int subLength ) const
String.cpp
124 {
125
126
127
128
(5 of 7)
return "";
""; // converted to a String object automatically
129
130
131
int len;
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
Outline
69
149
String.cpp
(6 of 7)
return length;
156 } // end function getLength
157
155
162
163
164
175
176 // overloaded input operator
177 istream &operator>>( istream &input, String &s )
Outline
70
178 {
179
180
181
182
String.cpp
(7 of 7)
1
2
3
4
5
6
7
8
9
10
using std::cout;
using std::endl;
using std::boolalpha;
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "String.h"
Outline
71
fig11_11.cpp
(1 of 5)
int main()
{
String s1( "happy" );
String
Stri
ng s2( " birthday" );
String s3;
// test overloaded equality and relational operators
Use overloaded stream insertion
cout << "s1 is \"" << s1 << "\"; s2 is \"" << s2
operator for Strings
<< "\"; s3 is \"" << s3 << '\"'
<< boolalpha << "\n\nThe results of comparing s2 and s1:"
<< "\ns2 == s1 yields " << ( s2 == s1 )
"\
<< "
\ns2 != s1 yields " << ( s2 != s1 )
"\
<< "
\ns2 > s1 yields " << ( s2 > s1 )
Use overloaded equality and
<< "\ns2 < s1 yields " << ( s2 < s1 )
relational operators for Strings
<< "\ns2 >= s1 yields " << ( s2 >= s1 )
<< "\
"\ns2 <= s1 yields " << ( s2 <= s1 );
31
32
if ( !s3 )
{
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
72
overloaded assignment
operator for Strings fig11_11.cpp
(2 of 5)
Use overloaded addition assignment
operator for Strings
61
62
63
64
65
Outline
73
fig11_11.cpp
66
67
// test destructor
68
delete s4Ptr;
(3 of 5)
69
70
71
s1[ 0 ] = 'H';
'H';
72
s1[ 6 ] = 'B';
'B';
73
cout << "\ns1 after s1[0] = 'H' and s1[6] = 'B' is: "
74
75
76
77
78
79
return 0;
80 } // end main
Outline
74
fig11_11.cpp
(4 of 5)
Testing !s3:
s3 is empty; assigning s1 to s3;
operator= called
s3 is "happy"
s1 += s2 yields s1 = happy birthday
s1 += " to you" yields
Conversion (and default) constructor:
constructor:
Destructor: to you
s1 = happy birthday to you
to you
Outline
75
fig11_11.cpp
(5 of 5)
*s4Ptr to *s4Ptr
called
assignment of a String to itself
76
77
78
79
80
81
82
83
Postfix increment
Returns by value
Returns temporary object with old value
rvalue (cannot be on left side of assignment)
84
85
Overloaded += operator
Function to test for leap years
Function to determine if day is last of month
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Fig.
// Date
#ifndef
#define
11.12: Date.h
class definition.
DATE_H
DATE_H
#include <iostream>
using std::ostream;
class Date
{
friend ostream &operator<<( ostream &, const Date & );
public:
public
:
Date( int m = 1, int d = 1, int y = 1900 ); // default constructor
int,
int,
void setDate( int
, int
, int ); // set month, day, year
Date &operator++(); // prefix increment operator
Date operator++( int ); // postfix increment operator
const Date &operator+=( int ); // add days, modify object
const;
bool leapYear( int ) const
; // is date in a leap year?
const;
bool endOfMonth( int ) const
; // is date at the end of month?
private:
private
:
int month;
int day;
Outline
86
Date.h
(1 of 1)
23
int year;
24
25
static const int days[]; // array of days per month
26
void helpIncrement(); // utility function for incrementing date
27 }; // end class Date
28
29 #endif
#include <iostream>
#include "Date.h"
Outline
87
5
6
{ 0, 31,
31, 28,
28, 31,
31, 30,
30, 31,
31, 30,
30, 31,
31, 31,
31, 30,
30, 31,
31, 30,
30, 31 };
Date.cpp
(1 of 4)
9
10 // Date constructor
11 Date::Date( int m, int d, int y )
12 {
13
setDate( m, d, y );
20
21
22
23
24
25
26
28
29 // overloaded prefix increment operator
30 Date &Date::operator++()
Outline
88
31 {
32
33
return *this
*this;
this; // reference return to create an lvalue
Date.cpp
(2 of 4)
41
helpIncrement();
42
43
44
52
53
return *this
*this;
this; // enables cascading
if ( testYear % 400 == 0 ||
60
61
return true;
true; // a leap year
year
62
63
Outline
89
Date.cpp
else
return false;
false; // not a leap year
(3 of 4)
79
if ( !endOfMonth( day ) )
80
81
Date.cpp
else
82
83
84
85
86
} // end if
87
88
89
90
month = 1; // first
first month of new year
91
92
Outline
90
(4 of 4)
} // end else
99
"March",
"March", "April",
"April", "May",
"May", "June",
"June", "July",
"July", "August",
"August",
100
"September",
"September", "October",
"October", "November",
"November", "December" };
101
output << monthName[ d.month ] << ' ' << d.day << ", " << d.year;
102
#include <iostream>
using std::cout;
using std::endl;
Outline
6
7
fig11_14.cpp
#include "Date.h" // Date class definition
8
9
91
(1 of 2)
int main()
10 {
11
12
13
14
15
cout << "d1 is " << d1 << "\nd2 is " << d2 << "\nd3 is " << d3;
16
17
18
d3.setDate( 2, 28,
28, 1992 );
19
20
cout << "\n++d3 is " << ++d3 << " (leap year allows 29th)";
29th)";
21
22
23
24
25
26
27
28
29
<< "
30
31
32
33
return 0;
is
is
is
92
34 } // end main
d1
d2
d3
Outline
January 1, 1900
December 27, 1992
January 1, 1900
(2 of 2)
d2 += 7 is January 3, 1993
d3 is February 28, 1992
++d3 is February 29, 1992 (leap year allows 29th)
Testing
d4 is
++d4 is
d4 is
Testing
d4 is
d4++ is
d4 is
93
94
Class string
Header <string>,
<string> namespace std
Can initialize string s1( "hi" );
Overloaded << (as in cout << s1)
s1
Overloaded relational operators
==,
== !=,
!= >=,
>= >, <=,
<= <
Assignment operator =
Concatenation (overloaded +=)
+=
95
Overloaded []
Access one character
No range checking (if subscript invalid)
Member function at
Accesses one character
Example
s1.at( 10 );
Has bounds checking, throws an exception if subscript is invalid
Will end program (learn more in Chapter 16)
2008 Pearson Education, Inc. All rights reserved.
#include <iostream>
using std::cout;
using std::endl;
Outline
96
fig11_15.cpp
#include <string>
using std::string;
of 4)
Passing strings to the string (1
constructor
9
10 int main()
11 {
12
13
14
string s3;
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
if ( s3.empty() )
31
32
33
s3 = s1;
s1; // assign s1 to s3
34
35
Outline
Member function empty
tests
if the string is empty
97
fig11_15.cpp
} // end if
(2 of 4)
36
37
38
39
40
41
42
43
44
s1 += " to you";
you";
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
Outline
98
60
61
62
63
*s4Ptr = *s4Ptr;
64
fig11_15.cpp
(3 of 4)
65
66
// test destructor
67
delete s4Ptr;
68
69
70
s1[ 0 ] = 'H';
'H';
71
s1[ 6 ] = 'B';
'B';
72
cout << "\ns1 after s1[0] = 'H' and s1[6] = 'B' is: "
73
74
75
76
77
78
return 0;
79 } // end main
Member function at
provides range checking
Outline
99
fig11_15.cpp
(4 of 4)
100
101
#include <iostream>
using std::cout;
using std::endl;
Outline
fig11_16.cpp
6
7
#include "Array.h"
(1 of 2)
8
9
102
10
11 int main()
12 {
13
14
15
16
return 0;
17 }
// end main
18
19 // print Array contents
20 void outputArray( const Array &arrayToOutput )
Outline
103
21 {
22
23
fig11_16.cpp
24 } // end outputArray
outputArray
The Array received has 7 elements. The contents are:
0
0
0
0
0
0
0
(2 of 2)
#ifndef ARRAY_H
#define ARRAY_H
Outline
104
5
6
#include <iostream>
using std::ostream;
using std::istream;
Array.h
(1 of 1)
9
10 class Array
11 {
12
13
14 public:
public:
15
16
17
~Array(); // destructor
18
19
20
21
22
23
24
25
26
Outline
return ! ( *this
*this == right ); // invokes
invokes Array::operator==
} // end function operator!=
Array.h
29
(2 of 2)
30
27
105
28
31
32
// subscript
subscript operator for const objects returns rvalue
33
34 private:
private:
35
36
106
107
#include <iostream>
using std::cout;
using std::endl;
Outline
Fig11_18.cpp
6
7
#include "Array.h"
8
9
108
10
(1 of 2)on the
Using keyword explicit
conversion constructor disallows this line to
erroneously call the conversion constructor
11 int main()
12 {
13
14
15
16
17
return 0;
18 }
// end main
19
20 // print array contents
21 void outputArray( const Array &arrayToOutput )
Outline
109
22 {
23
24
Fig11_18.cpp
25 } // end outputArray
outputArray
(2 of 2)
c:\
c:\cpphtp6_examples\
cpphtp6_examples\ch11\
ch11\Fig11_17_18\
Fig11_17_18\Fig11_18.cpp(15) : error C2664:
'outputArray' : cannot convert parameter 1 from 'int' to 'const Array &'
Reason: cannot convert from 'int' to 'const Array'
Constructor for class 'Array' is declared 'explicit'
110