View
217
Download
1
Embed Size (px)
Citation preview
More on Operator Overloading
CS-2303, C-Term 2010 1
More on Operator Overloading
CS-2303System Programming Concepts
(Slides include materials from The C Programming Language, 2nd edition, by Kernighan and Ritchie, from C: How to Program, 5th and 6th editions, by Deitel and Deitel, and from
The C++ Programming Language, 3rd edition, by Bjarne Stroustrup)
More on Operator Overloading
CS-2303, C-Term 2010 2
Case Study — Array Class
• Problems with pointer-based arrays in C++:–– 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.
• Can we do better?– I.e., can we create a data type that looks like an array
but has the missing properties
More on Operator Overloading
CS-2303, C-Term 2010 3
Point of Operator Overloading
• By using C++ classes and operator overloading, …
• … one can significantly change the capabilities of a built-in type
• In this case, of the built-in array type
More on Operator Overloading
CS-2303, C-Term 2010 4
Case Study — Array Class
• Implement an Array class with:–– Range checking– Array assignment ( = )– Arrays that know their own size.– Array comparisons with == and !=– Output/input of entire arrays with << and >>
Deitel & Deitel, §22.8
More on Operator Overloading
CS-2303, C-Term 2010 5
Array Class Copy Constructor
• Used whenever copy of object is needed:– Passing by value (return value or parameter).– Initializing an object with a copy of another of
same type.
Array newArray( oldArray ); or
Array newArray = oldArray;– Both are identical– newArray is a copy of oldArray.
More on Operator Overloading
CS-2303, C-Term 2010 6
Definition – Copy Constructor
• A constructor of some type T of the form
T (const & T);
• The single argument must be a const reference to an existing object of same type
• Creates a duplicate of the existing object• Used whenever a copy of an object is needed• Including arguments to functions, results returned
from functions
Copy constructors always
take
reference argument!
Reason: avoid infinite recursion!
More on Operator Overloading
CS-2303, C-Term 2010 7
1 // Fig. 22.6: Array.h
2 // Array class for storing arrays of integers.
3 #ifndef ARRAY_H
4 #define ARRAY_H
5
6 #include <iostream>
7 using std::ostream;
8 using std::istream;
9
10 class Array
11 {
12 friend ostream &operator<<( ostream &, const Array & );
13 friend istream &operator>>( istream &, Array & );
14 public:
15 Array( int = 10 ); // default constructor
16 Array( const Array & ); // copy constructor
17 ~Array(); // destructor
18 int getSize() const; // return size
19
20 const Array &operator=( const Array & ); // assignment operator
21 bool operator==( const Array & ) const; // equality operator
22
23 // inequality operator; returns opposite of == operator
24 bool operator!=( const Array &right ) const
25 {
26 return ! ( *this == right ); // invokes Array::operator==
27 } // end function operator!=
Most operators overloaded as member functions (except << and >>
which must be global functions)
Prototype for copy constructor
!= operator simply returns opposite of == operator – only need to define the == operator
Array Class Definition
More on Operator Overloading
CS-2303, C-Term 2010 8
1 // Fig. 22.6: Array.h
2 // Array class for storing arrays of integers.
3 #ifndef ARRAY_H
4 #define ARRAY_H
5
6 #include <iostream>
7 using std::ostream;
8 using std::istream;
9
10 class Array
11 {
12 friend ostream &operator<<( ostream &, const Array & );
13 friend istream &operator>>( istream &, Array & );
14 public:
15 Array( int = 10 ); // default constructor
16 Array( const Array & ); // copy constructor
17 ~Array(); // destructor
18 int getSize() const; // return size
19
20 const Array &operator=( const Array & ); // assignment operator
21 bool operator==( const Array & ) const; // equality operator
22
23 // inequality operator; returns opposite of == operator
24 bool operator!=( const Array &right ) const
25 {
26 return ! ( *this == right ); // invokes Array::operator==
27 } // end function operator!=
Array Class Definition
Note weird return type:–constant reference
Not explained in D&D
More on Operator Overloading
CS-2303, C-Term 2010 9
28
29 // subscript operator for non-const objects returns modifiable lvalue
30 int &operator[]( int );
31
32 // subscript operator for const objects returns rvalue
33 int operator[]( int ) const;
34 private:
35 int size; // pointer-based array size
36 int *ptr; // pointer to first element of pointer-based array
37 }; // end class Array
38
39 #endif
Operators for accessing specific elements of Array object
Note: An example of pointer data Note: An example of pointer data membermember
Array Class Definition (continued)
More on Operator Overloading
CS-2303, C-Term 2010 10
1 // Fig 22.7: Array.cpp
2 // Member-function definitions for class Array
3 #include <iostream>
4 using std::cerr;
5 using std::cout;
6 using std::cin;
7 using std::endl;
8
9 #include <iomanip>
10 using std::setw;
11
12 #include <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 size = ( arraySize > 0 ? arraySize : 10 ); // validate arraySize
21 ptr = new int[ size ]; // create space for pointer-based array
22
23 for ( int i = 0; i < size; i++ )
24 ptr[ i ] = 0; // set pointer-based array element
25 } // end Array default constructor
Array Class Implementation
More on Operator Overloading
CS-2303, C-Term 2010 11
26
27 // copy constructor for class Array;
28 // must receive a reference to prevent infinite recursion
29 Array::Array( const Array &arrayToCopy )
30 : size( arrayToCopy.size )
31 {
32 ptr = new int[ size ]; // create space for pointer-based array
33
34 for ( int i = 0; i < size; i++ )
35 ptr[ i ] = arrayToCopy.ptr[ i ]; // copy into object
36 } // end Array copy constructor
37
38 // destructor for class Array
39 Array::~Array()
40 {
41 delete [] ptr; // release pointer-based array space
42 } // end destructor
43
44 // return number of elements of Array
45 int Array::getSize() const
46 {
47 return size; // number of elements in Array
48 } // end function getSize
We must declare a new integer array so the objects do not point to the same memory
Array Class Implementation (continued)
More on Operator Overloading
CS-2303, C-Term 2010 12
49
50 // overloaded assignment operator;
51 // const return avoids: ( a1 = a2 ) = a3
52 const Array &Array::operator=( const Array &right )
53 {
54 if ( &right != this ) // avoid self-assignment
55 {
56 // for Arrays of different sizes, deallocate original
57 // left-side array, then allocate new left-side array
58 if ( size != right.size )
59 {
60 delete [] ptr; // release space
61 size = right.size; // resize this object
62 ptr = new int[ size ]; // create space for array copy
63 } // end inner if
64
65 for ( int i = 0; i < size; i++ )
66 ptr[ i ] = right.ptr[ i ]; // copy array into object
67 } // end outer if
68
69 return *this; // enables x = y = z, for example
70 } // end function operator=
Want to avoid self assignment
This would be dangerous if this is the same Array as right
Array Class Implementation (continued)Note that Copy Constructor andassignment are not the same thing.(But they are similar!)
More on Operator Overloading
CS-2303, C-Term 2010 13
71
72 // determine if two Arrays are equal and
73 // return true, otherwise return false
74 bool Array::operator==( const Array &right ) const
75 {
76 if ( size != right.size )
77 return false; // arrays of different number of elements
78
79 for ( int i = 0; i < size; i++ )
80 if ( ptr[ i ] != right.ptr[ i ] )
81 return false; // Array contents are not equal
82
83 return true; // Arrays are equal
84 } // end function operator==
85
86 // overloaded subscript operator for non-const Arrays;
87 // reference return creates a modifiable lvalue
88 int &Array::operator[]( int subscript )
89 {
90 // check for subscript out-of-range error
91 if ( subscript < 0 || subscript >= size )
92 {
93 cerr << "\nError: Subscript " << subscript
94 << " out of range" << endl;
95 exit( 1 ); // terminate program; subscript out of range
96 } // end if
97
98 return ptr[ subscript ]; // reference return
99 } // end function operator[]
integers1[ 5 ] calls integers1.operator[]( 5 )
Array Class Implementation (continued)
More on Operator Overloading
CS-2303, C-Term 2010 14
100
101 // overloaded subscript operator for const Arrays
102 // const reference return creates an rvalue
103 int Array::operator[]( int subscript ) const
104 {
105 // check for subscript out-of-range error
106 if ( subscript < 0 || subscript >= size )
107 {
108 cerr << "\nError: Subscript " << subscript
109 << " out of range" << endl;
110 exit( 1 ); // terminate program; subscript out of range
111 } // end if
112
113 return ptr[ subscript ]; // returns copy of this element
114 } // end function operator[]
115
116 // overloaded input operator for class Array;
117 // inputs values for entire Array
118 istream &operator>>( istream &input, Array &a )
119 {
120 for ( int i = 0; i < a.size; i++ )
121 input >> a.ptr[ i ];
122
123 return input; // enables cin >> x >> y;
124 } // end function
Array Class Implementation (continued)
Should be some errorchecking here
Notice the return type
More on Operator Overloading
CS-2303, C-Term 2010 15
125
126 // overloaded output operator for class Array
127 ostream &operator<<( ostream &output, const Array &a )
128 {
129 int i;
130
131 // output private ptr-based array
132 for ( i = 0; i < a.size; i++ )
133 {
134 output << setw( 12 ) << a.ptr[ i ];
135
136 if ( ( i + 1 ) % 4 == 0 ) // 4 numbers per row of output
137 output << endl;
138 } // end for
139
140 if ( i % 4 != 0 ) // end last line of output
141 output << endl;
142
143 return output; // enables cout << x << y;
144 } // end function operator<<
Array Class Implementation (continued)
Notice the return type
More on Operator Overloading
CS-2303, C-Term 2010 16
1 // Fig. 22.8: fig22_08.cpp
2 // Array class test program.
3 #include <iostream>
4 using std::cout;
5 using std::cin;
6 using std::endl;
7
8 #include "Array.h"
9
10 int main()
11 {
12 Array integers1( 7 ); // seven-element Array
13 Array integers2; // 10-element Array by default
14
15 // print integers1 size and contents
16 cout << "Size of Array integers1 is "
17 << integers1.getSize()
18 << "\nArray after initialization:\n" << integers1;
19
20 // print integers2 size and contents
21 cout << "\nSize of Array integers2 is "
22 << integers2.getSize()
23 << "\nArray after initialization:\n" << integers2;
24
25 // input and print integers1 and integers2
26 cout << "\nEnter 17 integers:" << endl;
27 cin >> integers1 >> integers2;
Retrieve number of elements in Array
Use overloaded >> operator to input
Array Class Usage
More on Operator Overloading
CS-2303, C-Term 2010 17
28
29 cout << "\nAfter input, the Arrays contain:\n"
30 << "integers1:\n" << integers1
31 << "integers2:\n" << integers2;
32
33 // use overloaded inequality (!=) operator
34 cout << "\nEvaluating: integers1 != integers2" << endl;
35
36 if ( integers1 != integers2 )
37 cout << "integers1 and integers2 are not equal" << endl;
38
39 // create Array integers3 using integers1 as an
40 // initializer; print size and contents
41 Array integers3( integers1 ); // invokes copy constructor
42
43 cout << "\nSize of Array integers3 is "
44 << integers3.getSize()
45 << "\nArray after initialization:\n" << integers3;
46
47 // use overloaded assignment (=) operator
48 cout << "\nAssigning integers2 to integers1:" << endl;
49 integers1 = integers2; // note target Array is smaller
50
51 cout << "integers1:\n" << integers1
52 << "integers2:\n" << integers2;
53
54 // use overloaded equality (==) operator
55 cout << "\nEvaluating: integers1 == integers2" << endl;
Use overloaded << operator to output
Use overloaded != operator
to test for inequality
Use copy constructor
Use overloaded = operator to assign
Array Class Usage (continued)
More on Operator Overloading
CS-2303, C-Term 2010 18
56
57 if ( integers1 == integers2 )
58 cout << "integers1 and integers2 are equal" << endl;
59
60 // use overloaded subscript operator to create rvalue
61 cout << "\nintegers1[5] is " << integers1[ 5 ];
62
63 // use overloaded subscript operator to create lvalue
64 cout << "\n\nAssigning 1000 to integers1[5]" << endl;
65 integers1[ 5 ] = 1000;
66 cout << "integers1:\n" << integers1;
67
68 // attempt to use out-of-range subscript
69 cout << "\nAttempt to assign 1000 to integers1[15]" << endl;
70 integers1[ 15 ] = 1000; // ERROR: out of range
71 return 0;
72 } // end main
Use overloaded == operator to test for equality
Use overloaded [] operator to access individual integers, with range-checking
Array Class Usage (continued)
More on Operator Overloading
CS-2303, C-Term 2010 19
Questions?
More on Operator Overloading
CS-2303, C-Term 2010 20
Note about Type Conversion
• Any single-argument constructor can be used as a type-conversion between the argument type and the object type
• May be invoked implicitly or explicitly• Explict:– let a and b be complex
a = b + complex(2.0)
• Implicit:– whenever compiler figures out it needs one type but has anothera = b + 2.0 /* NO overloaded ‘+’ operator for complex, real */
More on Operator Overloading
CS-2303, C-Term 2010 21
Forcing explicit Type Conversion
• Sometimes, you don’t want compiler to make an implicit conversion
• Prefix constructor by explicit in type definition– Example:– (line 15 of Array class definition)
explicit Array(int =10);
– Suppresses use of this constructor for an implicit type conversion.
More on Operator Overloading
CS-2303, C-Term 2010 22
Questions?