CSC 213 Chapter 8, Fall 2007

Notre Dame University–Louaize · Program Design and Data Abstraction II · 47 pages

All CSC 213 files
CSC 213 Chapter 8, Fall 2007, page 1

Stuck on a question? A tutor can walk you through it.

CSC 213 Chapter 8, Fall 2007, page 2 CSC 213 Chapter 8, Fall 2007, page 3 CSC 213 Chapter 8, Fall 2007, page 4 CSC 213 Chapter 8, Fall 2007, page 5 CSC 213 Chapter 8, Fall 2007, page 6 CSC 213 Chapter 8, Fall 2007, page 7 CSC 213 Chapter 8, Fall 2007, page 8 CSC 213 Chapter 8, Fall 2007, page 9 CSC 213 Chapter 8, Fall 2007, page 10

Showing the first 10 of 47 pages. Download the PDF to see all of it.

More CSC 213 files

Show the text of this chapter
1  2000 Prentice Hall, Inc. All rights reserved. Chapter 8 - Operator Overloading Outline 8.1 Introduction 8.2 Fundamentals of Operator Overloading 8.3 Restrictions on Operator Overloading 8.4 Operator Functions as Class Members vs. as friend Functions 8.5 Overloading Stream-Insertion and Stream-Extraction Operators 8.6 Overloading Unary Operators 8.7 Overloading Binary Operators 8.8 Case Study: An Array Class 8.9 Converting between Types 8.10 Case Study: A String Class 8.11 Overloading ++ and -- 8.12 Case Study: A Date Class 2  2000 Prentice Hall, Inc. All rights reserved. 8.1 Introduction • Operator overloading – Enabling C++’s operators to work with class objects – Using traditional operators with user-defined objects – Requires great care; when overloading is misused, program difficult to understand – Examples of already overloaded operators • Operator << is both the stream-insertion operator and the bitwise left-shift operator • + and -, perform arithmetic on multiple types – Compiler generates the appropriate code based on the manner in which the operator is used 3  2000 Prentice Hall, Inc. All rights reserved. 8.2 Fundamentals of Operator Overloading • Overloading an operator – Write function definition as normal – Function name is keyword operator followed by the symbol for the operator being overloaded – operator+ used to overload the addition operator (+) • Using operators – To use an operator on a class object it must be overloaded unless the assignment operator(=)or the address operator(&) • Assignment operator by default performs memberwise assignment • Address operator (&) by default returns the address of an object 4  2000 Prentice Hall, Inc. All rights reserved. 8.3 Restrictions on Operator Overloading • C++ operators that can be overloaded • C++ Operators that cannot be overloaded Operators that cannot be overloaded . .* :: ?: sizeof Operators that can be overloaded + - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- ->* , -> [] () new delete new[] delete[] 5  2000 Prentice Hall, Inc. All rights reserved. 8.3 Restrictions on Operator Overloading • Overloading restrictions – Precedence of an operator cannot be changed – Associativity of an operator cannot be changed – Arity (number of operands) cannot be changed • Unary operators remain unary, and binary operators remain binary • Operators &, *, + and - each have unary and binary versions • Unary and binary versions can be overloaded separately • No new operators can be created – Use only existing operators • No overloading operators for built-in types – Cannot change how two integers are added – Produces a syntax error 6  2000 Prentice Hall, Inc. All rights reserved. 8.4 Operator Functions as Class Members vs. as friend Functions • Member vs non-member – Operator functions can be member or non-member functions – When overloading ( ), [ ], -> or any of the assignment operators, must use a member function • Operator functions as member functions – Leftmost operand must be an object (or reference to an object) of the class • If left operand of a different type, operator function must be a non-member function • Operator functions as non-member functions – Must be friends if needs to access private or protected members – Enable the operator to be commutative 7  2000 Prentice Hall, Inc. All rights reserved. 8.5 Overloading Stream-Insertion and Stream-Extraction Operators • Overloaded << and >> operators – Overloaded to perform input/output for user-defined types – Left operand of types ostream & and istream & – Must be a non-member function because left operand is not an object of the class – Must be a friend function to access private data members  2000 Prentice Hall, Inc. All rights reserved. Outline 8 Outline 1. Class definition 1.1 Function definitions 1 // Fig. 8.3: fig08_03.cpp 2 // Overloading the stream-insertion and 3 // stream-extraction operators. 4 #include <iostream> 5 6 using std::cout; 7 using std::cin; 8 using std::endl; 9 using std::ostream; 10 using std::istream; 11 12 #include <iomanip> 13 14 using std::setw; 15 16 class PhoneNumber { 17 friend ostream &operator<<( ostream&, const PhoneNumber & ); 18 friend istream &operator>>( istream&, PhoneNumber & ); 19 20 private: 21 char areaCode[ 4 ]; // 3-digit area code and null 22 char exchange[ 4 ]; // 3-digit exchange and null 23 char line[ 5 ]; // 4-digit line and null 24 }; 25 26 // Overloaded stream-insertion operator (cannot be 27 // a member function if we would like to invoke it with 28 // cout << somePhoneNumber;). 29 ostream &operator<<( ostream &output, const PhoneNumber &num ) 30 { Notice function prototypes for overloaded operators >> and << They must be friend functions.  2000 Prentice Hall, Inc. All rights reserved. Outline 9 Outline 1.1 Function definition 1.2 Initialize variables 2. Get input 2.1 Assign to object 2.2 Output data 31 output << "(" << num.areaCode << ") " 32 << num.exchange << "-" << num.line; 33 return output; // enables cout << a << b << c; 34 } 35 36 istream &operator>>( istream &input, PhoneNumber &num ) 37 { 38 input.ignore(); // skip ( 39 input >> setw( 4 ) >> num.areaCode; // input area code 40 input.ignore( 2 ); // skip ) and space 41 input >> setw( 4 ) >> num.exchange; // input exchange 42 input.ignore(); // skip dash (-) 43 input >> setw( 5 ) >> num.line; // input line 44 return input; // enables cin >> a >> b >> c; 45 } 46 47 int main() 48 { 49 PhoneNumber phone; // create object phone 50 51 cout << "Enter phone number in the form (123) 456-7890:\n"; 52 53 // cin >> phone invokes operator>> function by 54 // issuing the call operator>>( cin, phone ). 55 cin >> phone; 56 57 // cout << phone invokes operator<< function by 58 // issuing the call operator<<( cout, phone ). 59 cout << "The phone number entered was: " << phone << endl; 60 return 0; 61 } The function call cin >> phone; interpreted as operator>>(cin, phone); input is an alias for cin, and num is an alias for phone.  2000 Prentice Hall, Inc. All rights reserved. Outline 10 Outline Program Output Enter phone number in the form (123) 456-7890: (800) 555-1212 The phone number entered was: (800) 555-1212 11  2000 Prentice Hall, Inc. All rights reserved. 8.6 Overloading Unary Operators • Overloading unary operators – Can be overloaded with no arguments or one argument – Should usually be implemented as member functions • Avoid friend functions and classes because they violate the encapsulation of a class – Example declaration as a member function: class String { public: bool operator!() const; ... }; 12  2000 Prentice Hall, Inc. All rights reserved. 8.6 Overloading Unary Operators – Example declaration as a non-member function class String { friend bool operator!( const String & ) ... } 13  2000 Prentice Hall, Inc. All rights reserved. 8.7 Overloading Binary Operators • Overloaded Binary operators – Non-static member function, one argument – Example: class String { public: const String &operator+=( const String & ); ... }; – y += z is equivalent to y.operator+=( z ) 14  2000 Prentice Hall, Inc. All rights reserved. 8.7 Overloading Binary Operators – Non-member function, two arguments – Example: class String { friend const String &operator+=( String &, const String & ); ... }; – y += z is equivalent to operator+=( y, z ) 15  2000 Prentice Hall, Inc. All rights reserved. 8.8 Case Study: An Array class • Implement an Array class with – Range checking – Array assignment – Arrays that know their size – Outputting/inputting entire arrays with << and >> – Array comparisons with == and !=  2000 Prentice Hall, Inc. All rights reserved. Outline 16 Outline 1. Class definition 1.1 Function prototypes 1 // Fig. 8.4: array1.h 2 // Simple class Array (for integers) 3 #ifndef ARRAY1_H 4 #define ARRAY1_H 5 6 #include <iostream> 7 8 using std::ostream; 9 using std::istream; 10 11 class Array { 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 const Array &operator=( const Array & ); // assign arrays 20 bool operator==( const Array & ) const; // compare equal 21 22 // Determine if two arrays are not equal and 23 // return true, otherwise return false (uses operator==). 24 bool operator!=( const Array &right ) const 25 { return ! ( *this == right ); } 26 27 int &operator[]( int ); // subscript operator 28 const int &operator[]( int ) const; // subscript operator 29 static int getArrayCount(); // Return count of 30 // arrays instantiated. 31 private: 32 int size; // size of the array 33 int *ptr; // pointer to first element of array 34 static int arrayCount; // # of Arrays instantiated Notice all the overloaded operators used to implement the class.  2000 Prentice Hall, Inc. All rights reserved. Outline 17 Outline 1. Load header 1.1 Function definitions 1.2 Array constructor 35 }; 36 37 #endif 38 // Fig 8.4: array1.cpp 39 // Member function definitions for class Array 40 #include <iostream> 41 42 using std::cout; 43 using std::cin; 44 using std::endl; 45 46 #include <iomanip> 47 48 using std::setw; 49 50 #include <cstdlib> 51 #include <cassert> 52 #include "array1.h" 53 54 // Initialize static data member at file scope 55 int Array::arrayCount = 0; // no objects yet 56 57 // Default constructor for class Array (default size 10) 58 Array::Array( int arraySize ) 59 { 60 size = ( arraySize > 0 ? arraySize : 10 ); 61 ptr = new int[ size ]; // create space for array 62 assert( ptr != 0 ); // terminate if memory not allocated 63 ++arrayCount; // count one more object 64 65 for ( int i = 0; i < size; i++ ) 66 ptr[ i ] = 0; // initialize array  2000 Prentice Hall, Inc. All rights reserved. Outline 18 Outline 1.3 Array destructor 1.4 operator= (assignment) 67 } 68 69 // Copy constructor for class Array 70 // must receive a reference to prevent infinite recursion 71 Array::Array( const Array &init ) : size( init.size ) 72 { 73 ptr = new int[ size ]; // create space for array 74 assert( ptr != 0 ); // terminate if memory not allocated 75 ++arrayCount; // count one more object 76 77 for ( int i = 0; i < size; i++ ) 78 ptr[ i ] = init.ptr[ i ]; // copy init into object 79 } 80 81 // Destructor for class Array 82 Array::~Array() 83 { 84 delete [] ptr; // reclaim space for array 85 --arrayCount; // one fewer object 86 } 87 88 // Get the size of the array 89 int Array::getSize() const { return size; } 90 91 // Overloaded assignment operator 92 // const return avoids: ( a1 = a2 ) = a3 93 const Array &Array::operator=( const Array &right ) 94 { 95 if ( &right != this ) { // check for self-assignment 96 97 // for arrays of different sizes, deallocate original 98 // left side array, then allocate new left side array. 99 if ( size != right.size ) { 100 delete [] ptr; // reclaim space  2000 Prentice Hall, Inc. All rights reserved. Outline 19 Outline 1.5 operator== (equality) 1.6 operator[] (subscript for non- const arrays) 101 size = right.size; // resize this object 102 ptr = new int[ size ]; // create space for array copy 103 assert( ptr != 0 ); // terminate if not allocated 104 } 105 106 for ( int i = 0; i < size; i++ ) 107 ptr[ i ] = right.ptr[ i ]; // copy array into object 108 } 109 110 return *this; // enables x = y = z; 111} 112 113// Determine if two arrays are equal and 114// return true, otherwise return false. 115bool Array::operator==( const Array &right ) const 116{ 117 if ( size != right.size ) 118 return false; // arrays of different sizes 119 120 for ( int i = 0; i < size; i++ ) 121 if ( ptr[ i ] != right.ptr[ i ] ) 122 return false; // arrays are not equal 123 124 return true; // arrays are equal 125} 126 127// Overloaded subscript operator for non-const Arrays 128// reference return creates an lvalue 129int &Array::operator[]( int subscript ) 130{ 131 // check for subscript out of range error 132 assert( 0 <= subscript && subscript < size );  2000 Prentice Hall, Inc. All rights reserved. Outline 20 Outline 1.6 operator[] (subscript for const arrays) 1.7 getArrayCount 1.8 operator>> (input array) 1.9 operator<< (output array) 133 134 return ptr[ subscript ]; // reference return 135} 136 137// Overloaded subscript operator for const Arrays 138// const reference return creates an rvalue 139const int &Array::operator[]( int subscript ) const 140{ 141 // check for subscript out of range error 142 assert( 0 <= subscript && subscript < size ); 143 144 return ptr[ subscript ]; // const reference return 145} 146 147// Return the number of Array objects instantiated 148// static functions cannot be const 149int Array::getArrayCount() { return arrayCount; } 150 151// Overloaded input operator for class Array; 152// inputs values for entire array. 153istream &operator>>( istream &input, Array &a ) 154{ 155 for ( int i = 0; i < a.size; i++ ) 156 input >> a.ptr[ i ]; 157 158 return input; // enables cin >> x >> y; 159} 160 161// Overloaded output operator for class Array 162ostream &operator<<( ostream &output, const Array &a ) 163{  2000 Prentice Hall, Inc. All rights reserved. Outline 21 Outline 1. Load header 164 int i; 165 166 for ( i = 0; i < a.size; i++ ) { 167 output << setw( 12 ) << a.ptr[ i ]; 168 169 if ( ( i + 1 ) % 4 == 0 ) // 4 numbers per row of output 170 output << endl; 171 } 172 173 if ( i % 4 != 0 ) 174 output << endl; 175 176 return output; // enables cout << x << y; 177} 178// Fig. 8.4: fig08_04.cpp 179// Driver for simple class Array 180#include <iostream> 181 182using std::cout; 183using std::cin; 184using std::endl; 185 186#include "array1.h" 187 188int main() 189{ 190 // no objects yet 191 cout << "# of arrays instantiated = " 192 << Array::getArrayCount() << '\n'; 193 # of arrays instantiated = 0  2000 Prentice Hall, Inc. All rights reserved. Outline 22 Outline 1.1 Initialize objects 2. Function calls 194 // create two arrays and print Array count 195 Array integers1( 7 ), integers2; 196 cout << "# of arrays instantiated = " 197 << Array::getArrayCount() << "\n\n"; 198 199 // print integers1 size and contents 200 cout << "Size of array integers1 is " 201 << integers1.getSize() 202 << "\nArray after initialization:\n" 203 << integers1 << '\n'; 204 205 // print integers2 size and contents 206 cout << "Size of array integers2 is " 207 << integers2.getSize() 208 << "\nArray after initialization:\n" 209 << integers2 << '\n'; 210 211 // input and print integers1 and integers2 212 cout << "Input 17 integers:\n"; 213 cin >> integers1 >> integers2; 214 cout << "After input, the arrays contain:\n" 215 << "integers1:\n" << integers1 216 << "integers2:\n" << integers2 << '\n'; 217 218 // use overloaded inequality (!=) operator 219 cout << "Evaluating: integers1 != integers2\n"; 220 if ( integers1 != integers2 ) 221 cout << "They are not equal\n"; 222 223 // create array integers3 using integers1 as an 224 // initializer; print size and contents 225 Array integers3( integers1 ); 226 # of arrays instantiated = 2 Size of array integers1 is 7 Array after initialization: 0 0 0 0 0 0 0 Size of array integers2 is 10 Array after initialization: 0 0 0 0 0 0 0 0 0 0 Input 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 3 4 5 6 7 integers2: 8 9 10 11 12 13 14 15 16 17 Evaluating: integers1 != integers2 They are not equal  2000 Prentice Hall, Inc. All rights reserved. Outline 23 Outline 227 cout << "\nSize of array integers3 is " 228 << integers3.getSize() 229 << "\nArray after initialization:\n" 230 << integers3 << '\n'; 231 232 // use overloaded assignment (=) operator 233 cout << "Assigning integers2 to integers1:\n"; 234 integers1 = integers2; 235 cout << "integers1:\n" << integers1 236 << "integers2:\n" << integers2 << '\n'; 237 238 // use overloaded equality (==) operator 239 cout << "Evaluating: integers1 == integers2\n"; 240 if ( integers1 == integers2 ) 241 cout << "They are equal\n\n"; 242 243 // use overloaded subscript operator to create rvalue 244 cout << "integers1[5] is " << integers1[ 5 ] << '\n'; 245 246 // use overloaded subscript operator to create lvalue 247 cout << "Assigning 1000 to integers1[5]\n"; 248 integers1[ 5 ] = 1000; 249 cout << "integers1:\n" << integers1 << '\n'; 250 251 // attempt to use out of range subscript 252 cout << "Attempt to assign 1000 to integers1[15]" << endl; 253 integers1[ 15 ] = 1000; // ERROR: out of range 254 255 return 0; 256} Assigning integers2 to integers1: integers1: 8 9 10 11 12 13 14 15 16 17 integers2: 8 9 10 11 12 13 14 15 16 17 2. Function calls Size of array integers3 is 7 Array after initialization: 1 2 3 4 5 6 7 integers1[5] is 13 Evaluating: integers1 == integers2 They are equal Assigning 1000 to integers1[5] integers1: 8 9 10 11 12 1000 14 15 16 17 Attempt to assign 1000 to integers1[15] Assertion failed: 0 <= subscript && subscript < size, file Array1.cpp, line 95 abnormal program termination  2000 Prentice Hall, Inc. All rights reserved. Outline 24 Outline Program Output # of arrays instantiated = 0 # of arrays instantiated = 2 Size of array integers1 is 7 Array after initialization: 0 0 0 0 0 0 0 Size of array integers2 is 10 Array after initialization: 0 0 0 0 0 0 0 0 0 0 Input 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 3 4 5 6 7 integers2: 8 9 10 11 12 13 14 15 16 17 Evaluating: integers1 != integers2 They are not equal Size of array integers3 is 7 Array after initialization: 1 2 3 4 5 6 7  2000 Prentice Hall, Inc. All rights reserved. Outline 25 Outline Program Output Evaluating: integers1 == integers2 They are equal integers1[5] is 13 Assigning 1000 to integers1[5] integers1: 8 9 10 11 12 1000 14 15 16 17 Attempt to assign 1000 to integers1[15] Assertion failed: 0 <= subscript && subscript < size, file Array1.cpp, line 95 abnormal program termination Assigning integers2 to integers1: integers1: 8 9 10 11 12 13 14 15 16 17 integers2: 8 9 10 11 12 13 14 15 16 17 26  2000 Prentice Hall, Inc. All rights reserved. 8.9 Converting between Types • Cast operator – Forces conversions among built-in types – Specifies conversions between user defined and built-in types – Conversion operator must be a non-static member function – Cannot be a friend function – Do not specify return type • Return type is the type to which the object is being converted – For user-defined class A A::operator char *() const; • Declares an overloaded cast operator function for creating a char * out of an A object 27  2000 Prentice Hall, Inc. All rights reserved. 8.9 Converting between Types A::operator int() const; • Declares an overloaded cast operator function for converting an object of A into an integer A::operator otherClass() const; • Declares an overloaded cast operator function for converting an object of A into an object of otherClass • Compiler and casting – Casting can prevent the need for overloading – If an object s of user-defined class String appears in a program where an ordinary char * is expected, such as cout << s; The compiler calls the overloaded cast operator function operator char * to convert the object into a char * and uses the resulting char * in the expression 28  2000 Prentice Hall, Inc. All rights reserved. 8.10 Case Study: A String Class • Build a class to handle strings – Class string in standard library (more Chapter 19) • Conversion constructor – Single-argument constructors that turn objects of other types into class objects  2000 Prentice Hall, Inc. All rights reserved. Outline 29 Outline 1. Class definition 1.1 Member functions, some definitions 1 // Fig. 8.5: string1.h 2 // Definition of a String class 3 #ifndef STRING1_H 4 #define STRING1_H 5 6 #include <iostream> 7 8 using std::ostream; 9 using std::istream; 10 11 class String { 12 friend ostream &operator<<( ostream &, const String & ); 13 friend istream &operator>>( istream &, String & ); 14 15 public: 16 String( const char * = "" ); // conversion/default ctor 17 String( const String & ); // copy constructor 18 ~String(); // destructor 19 const String &operator=( const String & ); // assignment 20 const String &operator+=( const String & ); // concatenation 21 bool operator!() const; // is String empty? 22 bool operator==( const String & ) const; // test s1 == s2 23 bool operator<( const String & ) const; // test s1 < s2 24 25 // test s1 != s2 26 bool operator!=( const String & right ) const 27 { return !( *this == right ); } 28 29 // test s1 > s2 30 bool operator>( const String &right ) const 31 { return right < *this; } 32 33 // test s1 <= s2  2000 Prentice Hall, Inc. All rights reserved. Outline 30 Outline 1.2 Member variables 34 bool operator<=( const String &right ) const 35 { return !( right < *this ); } 36 37 // test s1 >= s2 38 bool operator>=( const String &right ) const 39 { return !( *this < right ); } 40 41 char &operator[]( int ); // subscript operator 42 const char &operator[]( int ) const; // subscript operator 43 String operator()( int, int ); // return a substring 44 int getLength() const; // return string length 45 46 private: 47 int length; // string length 48 char *sPtr; // pointer to start of string 49 50 void setString( const char * ); // utility function 51 }; 52 53 #endif 54 // Fig. 8.5: string1.cpp 55 // Member function definitions for class String 56 #include <iostream> 57 58 using std::cout; 59 using std::endl; 60 61 #include <iomanip> 62 63 using std::setw; 64  2000 Prentice Hall, Inc. All rights reserved. Outline 31 Outline 1. Load header 1.1 Function definitions 1.2 Conversion constructor 1.3 Copy constructor 1.4 Destructor 1.5 operator= (assignment) 65 #include <cstring> 66 #include <cassert> 67 #include "string1.h" 68 69 // Conversion constructor: Convert char * to String 70 String::String( const char *s ) : length( strlen( s ) ) 71 { 72 cout << "Conversion constructor: " << s << '\n'; 73 setString( s ); // call utility function 74 } 75 76 // Copy constructor 77 String::String( const String &copy ) : length( copy.length ) 78 { 79 cout << "Copy constructor: " << copy.sPtr << '\n'; 80 setString( copy.sPtr ); // call utility function 81 } 82 83 // Destructor 84 String::~String() 85 { 86 cout << "Destructor: " << sPtr << '\n'; 87 delete [] sPtr; // reclaim string 88 } 89 90 // Overloaded = operator; avoids self assignment 91 const String &String::operator=( const String &right ) 92 { 93 cout << "operator= called\n"; 94 95 if ( &right != this ) { // avoid self assignment Conversion constructor: char * to String. Constructors and destructors will print when called.  2000 Prentice Hall, Inc. All rights reserved. Outline 32 Outline 1.6 operator+= (concatenation) 1.7 operator! (string empty?) 1.8 operator== (equality) 96 delete [] sPtr; // prevents memory leak 97 length = right.length; // new String length 98 setString( right.sPtr ); // call utility function 99 } 100 else 101 cout << "Attempted assignment of a String to itself\n"; 102 103 return *this; // enables cascaded assignments 104} 105 106// Concatenate right operand to this object and 107// store in this object. 108const String &String::operator+=( const String &right ) 109{ 110 char *tempPtr = sPtr; // hold to be able to delete 111 length += right.length; // new String length 112 sPtr = new char[ length + 1 ]; // create space 113 assert( sPtr != 0 ); // terminate if memory not allocated 114 strcpy( sPtr, tempPtr ); // left part of new String 115 strcat( sPtr, right.sPtr ); // right part of new String 116 delete [] tempPtr; // reclaim old space 117 return *this; // enables cascaded calls 118} 119 120// Is this String empty? 121bool String::operator!() const { return length == 0; } 122 123// Is this String equal to right String? 124bool String::operator==( const String &right ) const 125 { return strcmp( sPtr, right.sPtr ) == 0; } 126 127// Is this String less than right String?  2000 Prentice Hall, Inc. All rights reserved. Outline 33 Outline 1.9 operator< (less than) 1.10 operator[] (subscript) 1.11 operator[] (const subscript) 1.12 operator() (return substring) 128bool String::operator<( const String &right ) const 129 { return strcmp( sPtr, right.sPtr ) < 0; } 130 131// Return a reference to a character in a String as an lvalue. 132char &String::operator[]( int subscript ) 133{ 134 // First test for subscript out of range 135 assert( subscript >= 0 && subscript < length ); 136 137 return sPtr[ subscript ]; // creates lvalue 138} 139 140// Return a reference to a character in a String as an rvalue. 141const char &String::operator[]( int subscript ) const 142{ 143 // First test for subscript out of range 144 assert( subscript >= 0 && subscript < length ); 145 146 return sPtr[ subscript ]; // creates rvalue 147} 148 149// Return a substring beginning at index and 150// of length subLength 151String String::operator()( int index, int subLength ) 152{ 153 // ensure index is in range and substring length >= 0 154 assert( index >= 0 && index < length && subLength >= 0 ); 155 156 // determine length of substring 157 int len; 158 Notice the overloaded function call operator.  2000 Prentice Hall, Inc. All rights reserved. Outline 34 Outline 1.13 getLength 1.14 setString 159 if ( ( subLength == 0 ) || ( index + subLength > length ) ) 160 len = length - index; 161 else 162 len = subLength; 163 164 // allocate temporary array for substring and 165 // terminating null character 166 char *tempPtr = new char[ len + 1 ]; 167 assert( tempPtr != 0 ); // ensure space allocated 168 169 // copy substring into char array and terminate string 170 strncpy( tempPtr, &sPtr[ index ], len ); 171 tempPtr[ len ] = '\0'; 172 173 // Create temporary String object containing the substring 174 String tempString( tempPtr ); 175 delete [] tempPtr; // delete the temporary array 176 177 return tempString; // return copy of the temporary String 178} 179 180// Return string length 181int String::getLength() const { return length; } 182 183// Utility function to be called by constructors and 184// assignment operator. 185void String::setString( const char *string2 ) 186{ 187 sPtr = new char[ length + 1 ]; // allocate storage 188 assert( sPtr != 0 ); // terminate if memory not allocated 189 strcpy( sPtr, string2 ); // copy literal to object 190}  2000 Prentice Hall, Inc. All rights reserved. Outline 35 Outline 1.15 operator<< (output String) 1.16 operator>> (input String) ----------------------- 1. Load header 1.1 Initialize objects 191 192// Overloaded output operator 193ostream &operator<<( ostream &output, const String &s ) 194{ 195 output << s.sPtr; 196 return output; // enables cascading 197} 198 199// Overloaded input operator 200istream &operator>>( istream &input, String &s ) 201{ 202 char temp[ 100 ]; // buffer to store input 203 204 input >> setw( 100 ) >> temp; 205 s = temp; // use String class assignment operator 206 return input; // enables cascading 207} 208// Fig. 8.5: fig08_05.cpp 209// Driver for class String 210#include <iostream> 211 212using std::cout; 213using std::endl; 214 215#include "string1.h" 216 217int main() 218{ 219 String s1( "happy" ), s2( " birthday" ), s3; 220 Conversion constructor: happy Conversion constructor: birthday Conversion constructor:  2000 Prentice Hall, Inc. All rights reserved. Outline 36 Outline 2. Function calls 221 // test overloaded equality and relational operators 222 cout << "s1 is \"" << s1 << "\"; s2 is \"" << s2 223 << "\"; s3 is \"" << s3 << '\"' 224 << "\nThe results of comparing s2 and s1:" 225 << "\ns2 == s1 yields " 226 << ( s2 == s1 ? "true" : "false" ) 227 << "\ns2 != s1 yields " 228 << ( s2 != s1 ? "true" : "false" ) 229 << "\ns2 > s1 yields " 230 << ( s2 > s1 ? "true" : "false" ) 231 << "\ns2 < s1 yields " 232 << ( s2 < s1 ? "true" : "false" ) 233 << "\ns2 >= s1 yields " 234 << ( s2 >= s1 ? "true" : "false" ) 235 << "\ns2 <= s1 yields " 236 << ( s2 <= s1 ? "true" : "false" ); 237 238 // test overloaded String empty (!) operator 239 cout << "\n\nTesting !s3:\n"; 240 if ( !s3 ) { 241 cout << "s3 is empty; assigning s1 to s3;\n"; 242 s3 = s1; // test overloaded assignment 243 cout << "s3 is \"" << s3 << "\""; 244 } 245 246 // test overloaded String concatenation operator 247 cout << "\n\ns1 += s2 yields s1 = "; 248 s1 += s2; // test overloaded concatenation 249 cout << s1; 250 251 // test conversion constructor 252 cout << "\n\ns1 += \" to you\" yields\n"; 253 s1 += " to you"; // test conversion constructor s1 is "happy"; s2 is " birthday"; s3 is "" The results of comparing s2 and s1: s2 == s1 yields false s2 != s1 yields true s2 > s1 yields false s2 < s1 yields true s2 >= s1 yields false s2 <= s1 yields true 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 constructor: to you Destructor: to you  2000 Prentice Hall, Inc. All rights reserved. Outline 37 Outline 2. Function calls 254 cout << "s1 = " << s1 << "\n\n"; 255 256 // test overloaded function call operator () for substring 257 cout << "The substring of s1 starting at\n" 258 << "location 0 for 14 characters, s1(0, 14), is:\n" 259 << s1( 0, 14 ) << "\n\n"; 260 261 // test substring "to-end-of-String" option 262 cout << "The substring of s1 starting at\n" 263 << "location 15, s1(15, 0), is: " 264 << s1( 15, 0 ) << "\n\n"; // 0 is "to end of string" 265 266 // test copy constructor 267 String *s4Ptr = new String( s1 ); 268 cout << "*s4Ptr = " << *s4Ptr << "\n\n"; 269 270 // test assignment (=) operator with self-assignment 271 cout << "assigning *s4Ptr to *s4Ptr\n"; 272 *s4Ptr = *s4Ptr; // test overloaded assignment 273 cout << "*s4Ptr = " << *s4Ptr << '\n'; 274 275 // test destructor 276 delete s4Ptr; 277 278 // test using subscript operator to create lvalue 279 s1[ 0 ] = 'H'; 280 s1[ 6 ] = 'B'; 281 cout << "\ns1 after s1[0] = 'H' and s1[6] = 'B' is: " 282 << s1 << "\n\n"; 283 s1 = happy birthday