Operator overloading

2,617 views

Published on

C++ Operator Overloading Concept

Published in: Technology, Education
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,617
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
229
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Operator overloading

  1. 1. 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: 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 8.13 Standard Library Classes string and vector
  2. 2. 8.1 Introduction <ul><li>Use operators with objects (operator overloading) </li></ul><ul><ul><li>Clearer than function calls for certain classes </li></ul></ul><ul><ul><li>Operator sensitive to context </li></ul></ul><ul><li>Examples </li></ul><ul><ul><li><< </li></ul></ul><ul><ul><ul><li>Stream insertion, bitwise left-shift </li></ul></ul></ul><ul><ul><li>+ </li></ul></ul><ul><ul><ul><li>Performs arithmetic on multiple types (integers, floats, etc.) </li></ul></ul></ul><ul><li>Will discuss when to use operator overloading </li></ul>
  3. 3. 8.2 Fundamentals of Operator Overloading <ul><li>Types </li></ul><ul><ul><li>Built in ( int , char ) or user-defined </li></ul></ul><ul><ul><li>Can use existing operators with user-defined types </li></ul></ul><ul><ul><ul><li>Cannot create new operators </li></ul></ul></ul><ul><li>Overloading operators </li></ul><ul><ul><li>Create a function for the class </li></ul></ul><ul><ul><li>Name function operator followed by symbol </li></ul></ul><ul><ul><ul><li>Operator+ for the addition operator + </li></ul></ul></ul>
  4. 4. 8.2 Fundamentals of Operator Overloading <ul><li>Using operators on a class object </li></ul><ul><ul><li>It must be overloaded for that class </li></ul></ul><ul><ul><ul><li>Exceptions: </li></ul></ul></ul><ul><ul><ul><li>Assignment operator, = </li></ul></ul></ul><ul><ul><ul><ul><li>Memberwise assignment between objects </li></ul></ul></ul></ul><ul><ul><ul><li>Address operator, & </li></ul></ul></ul><ul><ul><ul><ul><li>Returns address of object </li></ul></ul></ul></ul><ul><ul><ul><li>Both can be overloaded </li></ul></ul></ul><ul><li>Overloading provides concise notation </li></ul><ul><ul><li>object2 = object1.add(object2); </li></ul></ul><ul><ul><li>object2 = object2 + object1; </li></ul></ul>
  5. 5. 8. 3 Restrictions on Operator Overloading <ul><li>Cannot change </li></ul><ul><ul><li>How operators act on built-in data types </li></ul></ul><ul><ul><ul><li>I.e., cannot change integer addition </li></ul></ul></ul><ul><ul><li>Precedence of operator (order of evaluation) </li></ul></ul><ul><ul><ul><li>Use parentheses to force order-of-operations </li></ul></ul></ul><ul><ul><li>Associativity (left-to-right or right-to-left) </li></ul></ul><ul><ul><li>Number of operands </li></ul></ul><ul><ul><ul><li>& is unitary, only acts on one operand </li></ul></ul></ul><ul><li>Cannot create new operators </li></ul><ul><li>Operators must be overloaded explicitly </li></ul><ul><ul><li>Overloading + does not overload += </li></ul></ul>
  6. 6. 8. 3 Restrictions on Operator Overloading
  7. 7. 8.4 Operator Functions As Class Members Vs. As Friend Functions <ul><li>Operator functions </li></ul><ul><ul><li>Member functions </li></ul></ul><ul><ul><ul><li>Use this keyword to implicitly get argument </li></ul></ul></ul><ul><ul><ul><li>Gets left operand for binary operators (like + ) </li></ul></ul></ul><ul><ul><ul><li>Leftmost object must be of same class as operator </li></ul></ul></ul><ul><ul><li>Non member functions </li></ul></ul><ul><ul><ul><li>Need parameters for both operands </li></ul></ul></ul><ul><ul><ul><li>Can have object of different class than operator </li></ul></ul></ul><ul><ul><ul><li>Must be a friend to access private or protected data </li></ul></ul></ul><ul><ul><li>Called when </li></ul></ul><ul><ul><ul><li>Left operand of binary operator of same class </li></ul></ul></ul><ul><ul><ul><li>Single operand of unitary operator of same class </li></ul></ul></ul>
  8. 8. 8.4 Operator Functions As Class Members Vs. As Friend Functions <ul><li>Overloaded << operator </li></ul><ul><ul><li>Left operand of type ostream & </li></ul></ul><ul><ul><ul><li>Such as cout object in cout << classObject </li></ul></ul></ul><ul><ul><li>Similarly, overloaded >> needs istream & </li></ul></ul><ul><ul><li>Thus, both must be non-member functions </li></ul></ul>
  9. 9. 8.4 Operator Functions As Class Members Vs. As Friend Functions <ul><li>Commutative operators </li></ul><ul><ul><li>May want + to be commutative </li></ul></ul><ul><ul><ul><li>So both “ a + b ” and “ b + a ” work </li></ul></ul></ul><ul><ul><li>Suppose we have two different classes </li></ul></ul><ul><ul><li>Overloaded operator can only be member function when its class is on left </li></ul></ul><ul><ul><ul><li>HugeIntClass + Long int </li></ul></ul></ul><ul><ul><ul><li>Can be member function </li></ul></ul></ul><ul><ul><li>When other way, need a non-member overload function </li></ul></ul><ul><ul><ul><li>Long int + HugeIntClass </li></ul></ul></ul>
  10. 10. 8.5 Overloading Stream-Insertion and Stream-Extraction Operators <ul><li><< and >> </li></ul><ul><ul><li>Already overloaded to process each built-in type </li></ul></ul><ul><ul><li>Can also process a user-defined class </li></ul></ul><ul><li>Example program </li></ul><ul><ul><li>Class PhoneNumber </li></ul></ul><ul><ul><ul><li>Holds a telephone number </li></ul></ul></ul><ul><ul><li>Print out formatted number automatically </li></ul></ul><ul><ul><ul><li>(123) 456-7890 </li></ul></ul></ul>
  11. 11. fig08_03.cpp (1 of 3) 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 // PhoneNumber class definition 17 class PhoneNumber { 18 friend ostream & operator <<( ostream&, const PhoneNumber & ); 19 friend istream & operator >>( istream&, PhoneNumber & ); 20 21 private : 22 char areaCode[ 4 ]; // 3-digit area code and null 23 char exchange[ 4 ]; // 3-digit exchange and null 24 char line[ 5 ]; // 4-digit line and null 25 26 }; // end class PhoneNumber Notice function prototypes for overloaded operators >> and << They must be non-member friend functions, since the object of class Phonenumber appears on the right of the operator. cin << object cout >> object
  12. 12. fig08_03.cpp (2 of 3) 27 28 // overloaded stream-insertion operator; cannot be 29 // a member function if we would like to invoke it with 30 // cout << somePhoneNumber; 31 ostream & operator <<( ostream &output, const PhoneNumber &num ) 32 { 33 output << &quot;(&quot; << num.areaCode << &quot;) &quot; 34 << num.exchange << &quot;-&quot; << num.line; 35 36 return output; // enables cout << a << b << c; 37 38 } // end function operator<< 39 40 // overloaded stream-extraction operator; cannot be 41 // a member function if we would like to invoke it with 42 // cin >> somePhoneNumber; 43 istream & operator >>( istream &input, PhoneNumber &num ) 44 { 45 input.ignore(); // skip ( 46 input >> setw( 4 ) >> num.areaCode; // input area code 47 input.ignore( 2 ); // skip ) and space 48 input >> setw( 4 ) >> num.exchange; // input exchange 49 input.ignore(); // skip dash (-) 50 input >> setw( 5 ) >> num.line; // input line 51 52 return input; // enables cin >> a >> b >> c; The expression: cout << phone; is interpreted as the function call: operator<<(cout, phone); output is an alias for cout. This allows objects to be cascaded. cout << phone1 << phone2; first calls operator<<(cout, phone1) , and returns cout . Next, cout << phone2 executes. ignore() skips specified number of characters from input (1 by default). Stream manipulator setw restricts number of characters read. setw(4) allows 3 characters to be read, leaving room for the null character.
  13. 13. fig08_03.cpp (3 of 3) fig08_03.cpp output (1 of 1) 53 54 } // end function operator>> 55 56 int main() 57 { 58 PhoneNumber phone; // create object phone 59 60 cout << &quot;Enter phone number in the form (123) 456-7890:n&quot; ; 61 62 // cin >> phone invokes operator>> by implicitly issuing 63 // the non-member function call operator>>( cin, phone ) 64 cin >> phone; 65 66 cout << &quot;The phone number entered was: &quot; ; 67 68 // cout << phone invokes operator<< by implicitly issuing 69 // the non-member function call operator<<( cout, phone ) 70 cout << phone << endl; 71 72 return 0 ; 73 74 } // end main Enter phone number in the form (123) 456-7890: (800) 555-1212 The phone number entered was: (800) 555-1212
  14. 14. 8.6 Overloading Unary Operators <ul><li>Overloading unary operators </li></ul><ul><ul><li>Non- static member function, no arguments </li></ul></ul><ul><ul><li>Non-member function, one argument </li></ul></ul><ul><ul><ul><li>Argument must be class object or reference to class object </li></ul></ul></ul><ul><ul><li>Remember, static functions only access static data </li></ul></ul>
  15. 15. 8.6 Overloading Unary Operators <ul><li>Upcoming example (8.10) </li></ul><ul><ul><li>Overload ! to test for empty string </li></ul></ul><ul><ul><li>If non- static member function, needs no arguments </li></ul></ul><ul><ul><ul><li>!s becomes s.operator!() </li></ul></ul></ul><ul><ul><ul><ul><li>class String { public: bool operator!() const; ... }; </li></ul></ul></ul></ul><ul><ul><li>If non-member function, needs one argument </li></ul></ul><ul><ul><ul><li>s! becomes operator!(s) </li></ul></ul></ul><ul><ul><ul><li>class String { friend bool operator!( const String & ) ... } </li></ul></ul></ul>
  16. 16. 8.7 Overloading Binary Operators <ul><li>Overloading binary operators </li></ul><ul><ul><li>Non- static member function, one argument </li></ul></ul><ul><ul><li>Non-member function, two arguments </li></ul></ul><ul><ul><ul><li>One argument must be class object or reference </li></ul></ul></ul><ul><li>Upcoming example </li></ul><ul><ul><li>If non- static member function, needs one argument </li></ul></ul><ul><ul><ul><li>class String { </li></ul></ul></ul><ul><ul><ul><li>public: </li></ul></ul></ul><ul><ul><ul><li>const String &operator+=( const String & ); </li></ul></ul></ul><ul><ul><ul><li>... </li></ul></ul></ul><ul><ul><ul><li>}; </li></ul></ul></ul><ul><ul><li>y += z equivalent to y.operator+=( z ) </li></ul></ul>
  17. 17. 8.7 Overloading Binary Operators <ul><li>Upcoming example </li></ul><ul><ul><li>If non-member function, needs two arguments </li></ul></ul><ul><ul><li>Example: </li></ul></ul><ul><ul><ul><li>class String { </li></ul></ul></ul><ul><ul><ul><li>friend const String &operator+=( </li></ul></ul></ul><ul><ul><ul><li>String &, const String & ); </li></ul></ul></ul><ul><ul><ul><li>... </li></ul></ul></ul><ul><ul><ul><li>}; </li></ul></ul></ul><ul><ul><li>y += z equivalent to operator+=( y, z ) </li></ul></ul>
  18. 18. 8.8 Case Study: Array class <ul><li>Arrays in C++ </li></ul><ul><ul><li>No range checking </li></ul></ul><ul><ul><li>Cannot be compared meaningfully with == </li></ul></ul><ul><ul><li>No array assignment (array names const pointers) </li></ul></ul><ul><ul><li>Cannot input/output entire arrays at once </li></ul></ul><ul><ul><ul><li>One element at a time </li></ul></ul></ul><ul><li>Example:Implement an Array class with </li></ul><ul><ul><li>Range checking </li></ul></ul><ul><ul><li>Array assignment </li></ul></ul><ul><ul><li>Arrays that know their size </li></ul></ul><ul><ul><li>Outputting/inputting entire arrays with << and >> </li></ul></ul><ul><ul><li>Array comparisons with == and != </li></ul></ul>
  19. 19. 8.8 Case Study: Array class <ul><li>Copy constructor </li></ul><ul><ul><li>Used whenever copy of object needed </li></ul></ul><ul><ul><ul><li>Passing by value (return value or parameter) </li></ul></ul></ul><ul><ul><ul><li>Initializing an object with a copy of another </li></ul></ul></ul><ul><ul><ul><ul><li>Array newArray( oldArray ); </li></ul></ul></ul></ul><ul><ul><ul><ul><li>newArray copy of oldArray </li></ul></ul></ul></ul><ul><ul><li>Prototype for class Array </li></ul></ul><ul><ul><ul><li>Array( const Array & ); </li></ul></ul></ul><ul><ul><ul><li>Must take reference </li></ul></ul></ul><ul><ul><ul><ul><li>Otherwise, pass by value </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Tries to make copy by calling copy constructor… </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Infinite loop </li></ul></ul></ul></ul>
  20. 20. array1.h (1 of 2) 1 // Fig. 8.4: array1.h 2 // Array class for storing arrays of 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 15 public : 16 Array( int = 10 ); // default constructor 17 Array( const Array & ); // copy constructor 18 ~Array(); // destructor 19 int getSize() const ; // return size 20 21 // assignment operator 22 const Array & operator =( const Array & ); 23 24 // equality operator 25 bool operator ==( const Array & ) const ; 26 Most operators overloaded as member functions (except << and >> , which must be non-member functions). Prototype for copy constructor.
  21. 21. array1.h (2 of 2) 27 // inequality operator; returns opposite of == operator 28 bool operator !=( const Array &right ) const 29 { 30 return ! ( * this == right ); // invokes Array::operator== 31 32 } // end function operator!= 33 34 // subscript operator for non-const objects returns lvalue 35 int & operator []( int ); 36 37 // subscript operator for const objects returns rvalue 38 const int & operator []( int ) const ; 39 40 private : 41 int size; // array size 42 int *ptr; // pointer to first element of array 43 44 }; // end class Array 45 46 #endif != operator simply returns opposite of == operator. Thus, only need to define the == operator.
  22. 22. array1.cpp (1 of 7) 1 // Fig 8.5: array1.cpp 2 // Member function definitions for class Array 3 #include <iostream> 4 5 using std::cout; 6 using std::cin; 7 using std::endl; 8 9 #include <iomanip> 10 11 using std::setw; 12 13 #include <new> // C++ standard &quot;new&quot; operator 14 15 #include <cstdlib> // exit function prototype 16 17 #include &quot;array1.h&quot; // Array class definition 18 19 // default constructor for class Array (default size 10) 20 Array::Array( int arraySize ) 21 { 22 // validate arraySize 23 size = ( arraySize > 0 ? arraySize : 10 ); 24 25 ptr = new int[ size ]; // create space for array 26
  23. 23. array1.cpp (2 of 7) 27 for ( int i = 0 ; i < size; i++ ) 28 ptr[ i ] = 0 ; // initialize array 29 30 } // end Array default constructor 31 32 // copy constructor for class Array; 33 // must receive a reference to prevent infinite recursion 34 Array::Array( const Array &arrayToCopy ) 35 : size( arrayToCopy.size ) 36 { 37 ptr = new int[ size ]; // create space for array 38 39 for ( int i = 0 ; i < size; i++ ) 40 ptr[ i ] = arrayToCopy.ptr[ i ]; // copy into object 41 42 } // end Array copy constructor 43 44 // destructor for class Array 45 Array::~Array() 46 { 47 delete [] ptr; // reclaim array space 48 49 } // end destructor 50 We must declare a new integer array so the objects do not point to the same memory.
  24. 24. array1.cpp (3 of 7) 51 // return size of array 52 int Array::getSize() const 53 { 54 return size; 55 56 } // end function getSize 57 58 // overloaded assignment operator; 59 // const return avoids: ( a1 = a2 ) = a3 60 const Array &Array:: operator =( const Array &right ) 61 { 62 if ( &right != this ) { // check for self-assignment 63 64 // for arrays of different sizes, deallocate original 65 // left-side array, then allocate new left-side array 66 if ( size != right.size ) { 67 delete [] ptr; // reclaim space 68 size = right.size; // resize this object 69 ptr = new int [ size ]; // create space for array copy 70 71 } // end inner if 72 73 for ( int i = 0 ; i < size; i++ ) 74 ptr[ i ] = right.ptr[ i ]; // copy array into object 75 76 } // end outer if Want to avoid self-assignment.
  25. 25. array1.cpp (4 of 7) 77 78 return * this ; // enables x = y = z, for example 79 80 } // end function operator= 81 82 // determine if two arrays are equal and 83 // return true, otherwise return false 84 bool Array:: operator ==( const Array &right ) const 85 { 86 if ( size != right.size ) 87 return false ; // arrays of different sizes 88 89 for ( int i = 0 ; i < size; i++ ) 90 91 if ( ptr[ i ] != right.ptr[ i ] ) 92 return false ; // arrays are not equal 93 94 return true ; // arrays are equal 95 96 } // end function operator== 97
  26. 26. array1.cpp (5 of 7) 98 // overloaded subscript operator for non-const Arrays 99 // reference return creates an lvalue 100 int &Array:: operator []( int subscript ) 101 { 102 // check for subscript out of range error 103 if ( subscript < 0 || subscript >= size ) { 104 cout << &quot;nError: Subscript &quot; << subscript 105 << &quot; out of range&quot; << endl; 106 107 exit( 1 ); // terminate program; subscript out of range 108 109 } // end if 110 111 return ptr[ subscript ]; // reference return 112 113 } // end function operator[] 114 integers1[5] calls integers1.operator[]( 5 ) exit() (header <cstdlib> ) ends the program.
  27. 27. array1.cpp (6 of 7) 115 // overloaded subscript operator for const Arrays 116 // const reference return creates an rvalue 117 const int &Array:: operator []( int subscript ) const 118 { 119 // check for subscript out of range error 120 if ( subscript < 0 || subscript >= size ) { 121 cout << &quot;nError: Subscript &quot; << subscript 122 << &quot; out of range&quot; << endl; 123 124 exit( 1 ); // terminate program; subscript out of range 125 126 } // end if 127 128 return ptr[ subscript ]; // const reference return 129 130 } // end function operator[] 131 132 // overloaded input operator for class Array; 133 // inputs values for entire array 134 istream & operator >>( istream &input, Array &a ) 135 { 136 for ( int i = 0 ; i < a.size; i++ ) 137 input >> a.ptr[ i ]; 138 139 return input; // enables cin >> x >> y; 140 141 } // end function
  28. 28. array1.cpp (7 of 7) 142 143 // overloaded output operator for class Array 144 ostream & operator <<( ostream &output, const Array &a ) 145 { 146 int i; 147 148 // output private ptr-based array 149 for ( i = 0 ; i < a.size; i++ ) { 150 output << setw( 12 ) << a.ptr[ i ]; 151 152 if ( ( i + 1 ) % 4 == 0 ) // 4 numbers per row of output 153 output << endl; 154 155 } // end for 156 157 if ( i % 4 != 0 ) // end last line of output 158 output << endl; 159 160 return output; // enables cout << x << y; 161 162 } // end function operator<<
  29. 29. fig08_06.cpp (1 of 3) 1 // Fig. 8.6: fig08_06.cpp 2 // Array class test program. 3 #include <iostream> 4 5 using std::cout; 6 using std::cin; 7 using std::endl; 8 9 #include &quot;array1.h&quot; 10 11 int main() 12 { 13 Array integers1( 7 ); // seven-element Array 14 Array integers2; // 10-element Array by default 15 16 // print integers1 size and contents 17 cout << &quot;Size of array integers1 is &quot; 18 << integers1.getSize() 19 << &quot;nArray after initialization:n&quot; << integers1; 20 21 // print integers2 size and contents 22 cout << &quot;nSize of array integers2 is &quot; 23 << integers2.getSize() 24 << &quot;nArray after initialization:n&quot; << integers2; 25
  30. 30. fig08_06.cpp (2 of 3) 26 // input and print integers1 and integers2 27 cout << &quot;nInput 17 integers:n&quot; ; 28 cin >> integers1 >> integers2; 29 30 cout << &quot;nAfter input, the arrays contain:n&quot; 31 << &quot;integers1:n&quot; << integers1 32 << &quot;integers2:n&quot; << integers2; 33 34 // use overloaded inequality (!=) operator 35 cout << &quot;nEvaluating: integers1 != integers2n&quot; ; 36 37 if ( integers1 != integers2 ) 38 cout << &quot;integers1 and integers2 are not equaln&quot; ; 39 40 // create array integers3 using integers1 as an 41 // initializer; print size and contents 42 Array integers3( integers1 ); // calls copy constructor 43 44 cout << &quot;nSize of array integers3 is &quot; 45 << integers3.getSize() 46 << &quot;nArray after initialization:n&quot; << integers3; 47
  31. 31. fig08_06.cpp (3 of 3) 48 // use overloaded assignment (=) operator 49 cout << &quot;nAssigning integers2 to integers1:n&quot; ; 50 integers1 = integers2; // note target is smaller 51 52 cout << &quot;integers1:n&quot; << integers1 53 << &quot;integers2:n&quot; << integers2; 54 55 // use overloaded equality (==) operator 56 cout << &quot;nEvaluating: integers1 == integers2n&quot; ; 57 58 if ( integers1 == integers2 ) 59 cout << &quot;integers1 and integers2 are equaln&quot; ; 60 61 // use overloaded subscript operator to create rvalue 62 cout << &quot;nintegers1[5] is &quot; << integers1[ 5 ]; 63 64 // use overloaded subscript operator to create lvalue 65 cout << &quot;nnAssigning 1000 to integers1[5]n&quot; ; 66 integers1[ 5 ] = 1000 ; 67 cout << &quot;integers1:n&quot; << integers1; 68 69 // attempt to use out-of-range subscript 70 cout << &quot;nAttempt to assign 1000 to integers1[15]&quot; << endl; 71 integers1[ 15 ] = 1000; // ERROR: out of range 72 73 return 0 ; 74 75 } // end main
  32. 32. fig08_06.cpp output (1 of 3)   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
  33. 33. fig08_06.cpp output (2 of 3) Evaluating: integers1 != integers2 integers1 and integers2 are not equal   Size of array integers3 is 7 Array after initialization: 1 2 3 4 5 6 7   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   Evaluating: integers1 == integers2 integers1 and integers2 are equal   integers1[5] is 13  
  34. 34. fig08_06.cpp output (3 of 3) Assigning 1000 to integers1[5] integers1: 8 9 10 11 12 1000 14 15 16 17   Attempt to assign 1000 to integers1[15]   Error: Subscript 15 out of range
  35. 35. 8.9 Converting between Types <ul><li>Casting </li></ul><ul><ul><li>Traditionally, cast integers to floats, etc. </li></ul></ul><ul><ul><li>May need to convert between user-defined types </li></ul></ul><ul><li>Cast operator (conversion operator) </li></ul><ul><ul><li>Convert from </li></ul></ul><ul><ul><ul><li>One class to another </li></ul></ul></ul><ul><ul><ul><li>Class to built-in type ( int , char , etc.) </li></ul></ul></ul><ul><ul><li>Must be non- static member function </li></ul></ul><ul><ul><ul><li>Cannot be friend </li></ul></ul></ul><ul><ul><li>Do not specify return type </li></ul></ul><ul><ul><ul><li>Implicitly returns type to which you are converting </li></ul></ul></ul>
  36. 36. 8.9 Converting between Types <ul><li>Example </li></ul><ul><ul><li>Prototype </li></ul></ul><ul><ul><ul><li>A::operator char *() const; </li></ul></ul></ul><ul><ul><ul><li>Casts class A to a temporary char * </li></ul></ul></ul><ul><ul><ul><li>(char *)s calls s.operator char*() </li></ul></ul></ul><ul><ul><li>Also </li></ul></ul><ul><ul><ul><li>A::operator int() const; </li></ul></ul></ul><ul><ul><ul><li>A::operator OtherClass() const; </li></ul></ul></ul>
  37. 37. 8.9 Converting between Types <ul><li>Casting can prevent need for overloading </li></ul><ul><ul><li>Suppose class String can be cast to char * </li></ul></ul><ul><ul><li>cout << s; // s is a String </li></ul></ul><ul><ul><ul><li>Compiler implicitly converts s to char * </li></ul></ul></ul><ul><ul><ul><li>Do not have to overload << </li></ul></ul></ul><ul><ul><li>Compiler can only do 1 cast </li></ul></ul>
  38. 38. 8.10 Case Study: A String Class <ul><li>Build class String </li></ul><ul><ul><li>String creation, manipulation </li></ul></ul><ul><ul><li>Class string in standard library (more Chapter 15) </li></ul></ul><ul><li>Conversion constructor </li></ul><ul><ul><li>Single-argument constructor </li></ul></ul><ul><ul><li>Turns objects of other types into class objects </li></ul></ul><ul><ul><ul><li>String s1(“hi”); </li></ul></ul></ul><ul><ul><ul><li>Creates a String from a char * </li></ul></ul></ul><ul><ul><li>Any single-argument constructor is a conversion constructor </li></ul></ul>
  39. 39. string1.h (1 of 3) 1 // Fig. 8.7: string1.h 2 // String class definition. 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 * = &quot;&quot; ); // conversion/default ctor 17 String( const String & ); // copy constructor 18 ~String(); // destructor 19 20 const String & operator =( const String & ); // assignment 21 const String & operator +=( const String & ); // concatenation 22 23 bool operator !() const ; // is String empty? 24 bool operator ==( const String & ) const ; // test s1 == s2 25 bool operator <( const String & ) const ; // test s1 < s2 26 Conversion constructor to make a String from a char * . s1 += s2 interpreted as s1.operator+=(s2) Can also concatenate a String and a char * because the compiler will cast the char * argument to a String . However, it can only do 1 level of casting.
  40. 40. string1.h (2 of 3) 27 // test s1 != s2 28 bool operator !=( const String & right ) const 29 { 30 return !( * this == right ); 31 32 } // end function operator!= 33 34 // test s1 > s2 35 bool operator >( const String &right ) const 36 { 37 return right < * this ; 38 39 } // end function operator> 40 41 // test s1 <= s2 42 bool operator <=( const String &right ) const 43 { 44 return !( right < * this ); 45 46 } // end function operator <= 47 48 // test s1 >= s2 49 bool operator >=( const String &right ) const 50 { 51 return !( * this < right ); 52 53 } // end function operator>=
  41. 41. string1.h (3 of 3) 54 55 char & operator []( int ); // subscript operator 56 const char & operator []( int ) const ; // subscript operator 57 58 String operator ()( int , int ); // return a substring 59 60 int getLength() const ; // return string length 61 62 private : 63 int length; // string length 64 char *sPtr; // pointer to start of string 65 66 void setString( const char * ); // utility function 67 68 }; // end class String 69 70 #endif Overload the function call operator () to return a substring. This operator can have any amount of operands. Two overloaded subscript operators, for const and non- const objects.
  42. 42. string1.cpp (1 of 8) 1 // Fig. 8.8: string1.cpp 2 // Member function definitions for class String. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include <iomanip> 9 10 using std::setw; 11 12 #include <new> // C++ standard &quot;new&quot; operator 13 14 #include <cstring> // strcpy and strcat prototypes 15 #include <cstdlib> // exit prototype 16 17 #include &quot;string1.h&quot; // String class definition 18 19 // conversion constructor converts char * to String 20 String::String( const char *s ) 21 : length( strlen( s ) ) 22 { 23 cout << &quot;Conversion constructor: &quot; << s << 'n' ; 24 setString( s ); // call utility function 25 26 } // end String conversion constructor
  43. 43. string1.cpp (2 of 8) 27 28 // copy constructor 29 String::String( const String &copy ) 30 : length( copy.length ) 31 { 32 cout << &quot;Copy constructor: &quot; << copy.sPtr << 'n' ; 33 setString( copy.sPtr ); // call utility function 34 35 } // end String copy constructor 36 37 // destructor 38 String::~String() 39 { 40 cout << &quot;Destructor: &quot; << sPtr << 'n' ; 41 delete [] sPtr; // reclaim string 42 43 } // end ~String destructor 44 45 // overloaded = operator; avoids self assignment 46 const String &String:: operator =( const String &right ) 47 { 48 cout << &quot;operator= calledn&quot; ; 49 50 if ( &right != this ) { // avoid self assignment 51 delete [] sPtr; // prevents memory leak 52 length = right.length; // new String length 53 setString( right.sPtr ); // call utility function 54 }
  44. 44. string1.cpp (3 of 8) 55 56 else 57 cout << &quot;Attempted assignment of a String to itselfn&quot; ; 58 59 return * this ; // enables cascaded assignments 60 61 } // end function operator= 62 63 // concatenate right operand to this object and 64 // store in this object. 65 const String &String:: operator +=( const String &right ) 66 { 67 size_t newLength = length + right.length; // new length 68 char *tempPtr = new char [ newLength + 1 ]; // create memory 69 70 strcpy( tempPtr, sPtr ); // copy sPtr 71 strcpy( tempPtr + length, right.sPtr ); // copy right.sPtr 72 73 delete [] sPtr; // reclaim old space 74 sPtr = tempPtr; // assign new array to sPtr 75 length = newLength; // assign new length to length 76 77 return * this ; // enables cascaded calls 78 79 } // end function operator+= 80
  45. 45. string1.cpp (4 of 8) 81 // is this String empty? 82 bool String:: operator !() const 83 { 84 return length == 0 ; 85 86 } // end function operator! 87 88 // is this String equal to right String? 89 bool String:: operator ==( const String &right ) const 90 { 91 return strcmp( sPtr, right.sPtr ) == 0 ; 92 93 } // end function operator== 94 95 // is this String less than right String? 96 bool String:: operator <( const String &right ) const 97 { 98 return strcmp( sPtr, right.sPtr ) < 0 ; 99 100 } // end function operator< 101
  46. 46. string1.cpp (5 of 8) 102 // return reference to character in String as lvalue 103 char &String:: operator []( int subscript ) 104 { 105 // test for subscript out of range 106 if ( subscript < 0 || subscript >= length ) { 107 cout << &quot;Error: Subscript &quot; << subscript 108 << &quot; out of range&quot; << endl; 109 110 exit( 1 ); // terminate program 111 } 112 113 return sPtr[ subscript ]; // creates lvalue 114 115 } // end function operator[] 116 117 // return reference to character in String as rvalue 118 const char &String:: operator []( int subscript ) const 119 { 120 // test for subscript out of range 121 if ( subscript < 0 || subscript >= length ) { 122 cout << &quot;Error: Subscript &quot; << subscript 123 << &quot; out of range&quot; << endl; 124 125 exit( 1 ); // terminate program 126 } 127 128 return sPtr[ subscript ]; // creates rvalue 129 130 } // end function operator[]
  47. 47. string1.cpp (6 of 8) 131 132 // return a substring beginning at index and 133 // of length subLength 134 String String:: operator ()( int index, int subLength ) 135 { 136 // if index is out of range or substring length < 0, 137 // return an empty String object 138 if ( index < 0 || index >= length || subLength < 0 ) 139 return &quot;&quot; ; // converted to a String object automatically 140 141 // determine length of substring 142 int len; 143 144 if ( ( subLength == 0 ) || ( index + subLength > length ) ) 145 len = length - index; 146 else 147 len = subLength; 148 149 // allocate temporary array for substring and 150 // terminating null character 151 char *tempPtr = new char [ len + 1 ]; 152 153 // copy substring into char array and terminate string 154 strncpy( tempPtr, &sPtr[ index ], len ); 155 tempPtr[ len ] = '0' ;
  48. 48. string1.cpp (7 of 8) 156 157 // create temporary String object containing the substring 158 String tempString( tempPtr ); 159 delete [] tempPtr; // delete temporary array 160 161 return tempString; // return copy of the temporary String 162 163 } // end function operator() 164 165 // return string length 166 int String::getLength() const 167 { 168 return length; 169 170 } // end function getLenth 171 172 // utility function called by constructors and operator= 173 void String::setString( const char *string2 ) 174 { 175 sPtr = new char [ length + 1 ]; // allocate memory 176 strcpy( sPtr, string2 ); // copy literal to object 177 178 } // end function setString
  49. 49. string1.cpp (8 of 8) 179 180 // overloaded output operator 181 ostream & operator <<( ostream &output, const String &s ) 182 { 183 output << s.sPtr; 184 185 return output; // enables cascading 186 187 } // end function operator<< 188 189 // overloaded input operator 190 istream & operator >>( istream &input, String &s ) 191 { 192 char temp[ 100 ]; // buffer to store input 193 194 input >> setw( 100 ) >> temp; 195 s = temp; // use String class assignment operator 196 197 return input; // enables cascading 198 199 } // end function operator>>
  50. 50. fig08_09.cpp (1 of 4) 1 // Fig. 8.9: fig08_09.cpp 2 // String class test program. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include &quot;string1.h&quot; 9 10 int main() 11 { 12 String s1( &quot;happy&quot; ); 13 String s2( &quot; birthday&quot; ); 14 String s3; 15 16 // test overloaded equality and relational operators 17 cout << &quot;s1 is &quot;&quot; << s1 << &quot;&quot;; s2 is &quot;&quot; << s2 18 << &quot;&quot;; s3 is &quot;&quot; << s3 << '&quot;' 19 << &quot;nnThe results of comparing s2 and s1:&quot; 20 << &quot;ns2 == s1 yields &quot; 21 << ( s2 == s1 ? &quot;true&quot; : &quot;false&quot; ) 22 << &quot;ns2 != s1 yields &quot; 23 << ( s2 != s1 ? &quot;true&quot; : &quot;false&quot; ) 24 << &quot;ns2 > s1 yields &quot; 25 << ( s2 > s1 ? &quot;true&quot; : &quot;false&quot; )
  51. 51. fig08_09.cpp (2 of 4) 26 << &quot;ns2 < s1 yields &quot; 27 << ( s2 < s1 ? &quot;true&quot; : &quot;false&quot; ) 28 << &quot;ns2 >= s1 yields &quot; 29 << ( s2 >= s1 ? &quot;true&quot; : &quot;false&quot; ) 30 << &quot;ns2 <= s1 yields &quot; 31 << ( s2 <= s1 ? &quot;true&quot; : &quot;false&quot; ); 32 33 // test overloaded String empty (!) operator 34 cout << &quot;nnTesting !s3:n&quot; ; 35 36 if ( !s3 ) { 37 cout << &quot;s3 is empty; assigning s1 to s3;n&quot; ; 38 s3 = s1; // test overloaded assignment 39 cout << &quot;s3 is &quot;&quot; << s3 << &quot;&quot;&quot; ; 40 } 41 42 // test overloaded String concatenation operator 43 cout << &quot;nns1 += s2 yields s1 = &quot; ; 44 s1 += s2; // test overloaded concatenation 45 cout << s1; 46 47 // test conversion constructor 48 cout << &quot;nns1 += &quot; to you&quot; yieldsn&quot; ; 49 s1 += &quot; to you&quot; ; // test conversion constructor 50 cout << &quot;s1 = &quot; << s1 << &quot;nn&quot; ;
  52. 52. fig08_09.cpp (3 of 4) 51 52 // test overloaded function call operator () for substring 53 cout << &quot;The substring of s1 starting atn&quot; 54 << &quot;location 0 for 14 characters, s1(0, 14), is:n&quot; 55 << s1( 0 , 14 ) << &quot;nn&quot; ; 56 57 // test substring &quot;to-end-of-String&quot; option 58 cout << &quot;The substring of s1 starting atn&quot; 59 << &quot;location 15, s1(15, 0), is: &quot; 60 << s1( 15 , 0 ) << &quot;nn&quot; ; // 0 is &quot;to end of string&quot; 61 62 // test copy constructor 63 String *s4Ptr = new String( s1 ); 64 cout << &quot;n*s4Ptr = &quot; << *s4Ptr << &quot;nn&quot; ; 65 66 // test assignment (=) operator with self-assignment 67 cout << &quot;assigning *s4Ptr to *s4Ptrn&quot; ; 68 *s4Ptr = *s4Ptr; // test overloaded assignment 69 cout << &quot;*s4Ptr = &quot; << *s4Ptr << 'n' ; 70 71 // test destructor 72 delete s4Ptr; 73
  53. 53. fig08_09.cpp (4 of 4) 74 // test using subscript operator to create lvalue 75 s1[ 0 ] = 'H' ; 76 s1[ 6 ] = 'B' ; 77 cout << &quot;ns1 after s1[0] = 'H' and s1[6] = 'B' is: &quot; 78 << s1 << &quot;nn&quot; ; 79 80 // test subscript out of range 81 cout << &quot;Attempt to assign 'd' to s1[30] yields:&quot; << endl; 82 s1[ 30 ] = 'd'; // ERROR: subscript out of range 83 84 return 0; 85 86 } // end main
  54. 54. fig08_09.cpp (1 of 3) Conversion constructor: happy Conversion constructor: birthday Conversion constructor: s1 is &quot;happy&quot;; s2 is &quot; birthday&quot;; s3 is &quot;&quot;   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 &quot;happy&quot;   s1 += s2 yields s1 = happy birthday   s1 += &quot; to you&quot; yields Conversion constructor: to you Destructor: to you s1 = happy birthday to you The constructor and destructor are called for the temporary String (converted from the char * “to you” ).
  55. 55. fig08_09.cpp (2 of 3) Conversion constructor: happy birthday Copy constructor: happy birthday Destructor: happy birthday The substring of s1 starting at location 0 for 14 characters, s1(0, 14), is: happy birthday   Destructor: happy birthday Conversion constructor: to you Copy constructor: to you Destructor: to you The substring of s1 starting at location 15, s1(15, 0), is: to you   Destructor: to you Copy constructor: happy birthday to you   *s4Ptr = happy birthday to you   assigning *s4Ptr to *s4Ptr operator= called Attempted assignment of a String to itself *s4Ptr = happy birthday to you Destructor: happy birthday to you  
  56. 56. fig08_09.cpp (3 of 3) s1 after s1[0] = 'H' and s1[6] = 'B' is: Happy Birthday to you   Attempt to assign 'd' to s1[30] yields: Error: Subscript 30 out of range
  57. 57. 8.11 Overloading ++ and -- <ul><li>Increment/decrement operators can be overloaded </li></ul><ul><ul><li>Add 1 to a Date object, d1 </li></ul></ul><ul><ul><li>Prototype (member function) </li></ul></ul><ul><ul><ul><li>Date &operator++(); </li></ul></ul></ul><ul><ul><ul><li>++d1 same as d1.operator++() </li></ul></ul></ul><ul><ul><li>Prototype (non-member) </li></ul></ul><ul><ul><ul><li>Friend Date &operator++( Date &); </li></ul></ul></ul><ul><ul><ul><li>++d1 same as operator++( d1 ) </li></ul></ul></ul>
  58. 58. 8.11 Overloading ++ and -- <ul><li>To distinguish pre/post increment </li></ul><ul><ul><li>Post increment has a dummy parameter </li></ul></ul><ul><ul><ul><li>int of 0 </li></ul></ul></ul><ul><ul><li>Prototype (member function) </li></ul></ul><ul><ul><ul><li>Date operator++( int ); </li></ul></ul></ul><ul><ul><ul><li>d1++ same as d1.operator++( 0 ) </li></ul></ul></ul><ul><ul><li>Prototype (non-member) </li></ul></ul><ul><ul><ul><li>friend Date operator++( Data &, int ); </li></ul></ul></ul><ul><ul><ul><li>d1++ same as operator++( d1, 0 ) </li></ul></ul></ul><ul><ul><li>Integer parameter does not have a name </li></ul></ul><ul><ul><ul><li>Not even in function definition </li></ul></ul></ul>
  59. 59. 8.11 Overloading ++ and -- <ul><li>Return values </li></ul><ul><ul><li>Preincrement </li></ul></ul><ul><ul><ul><li>Returns by reference ( Date & ) </li></ul></ul></ul><ul><ul><ul><li>lvalue (can be assigned) </li></ul></ul></ul><ul><ul><li>Postincrement </li></ul></ul><ul><ul><ul><li>Returns by value </li></ul></ul></ul><ul><ul><ul><li>Returns temporary object with old value </li></ul></ul></ul><ul><ul><ul><li>rvalue (cannot be on left side of assignment) </li></ul></ul></ul><ul><li>Decrement operator analogous </li></ul>
  60. 60. 8.12 Case Study: A Date Class <ul><li>Example Date class </li></ul><ul><ul><li>Overloaded increment operator </li></ul></ul><ul><ul><ul><li>Change day, month and year </li></ul></ul></ul><ul><ul><li>Overloaded += operator </li></ul></ul><ul><ul><li>Function to test for leap years </li></ul></ul><ul><ul><li>Function to determine if day is last of month </li></ul></ul>
  61. 61. date1.h (1 of 2) 1 // Fig. 8.10: date1.h 2 // Date class definition. 3 #ifndef DATE1_H 4 #define DATE1_H 5 #include <iostream> 6 7 using std::ostream; 8 9 class Date { 10 friend ostream & operator <<( ostream &, const Date & ); 11 12 public : 13 Date( int m = 1 , int d = 1 , int y = 1900 ); // constructor 14 void setDate( int , int , int ); // set the date 15 16 Date & operator ++(); // preincrement operator 17 Date operator ++( int ); // postincrement operator 18 19 const Date & operator +=( int ); // add days, modify object 20 21 bool leapYear( int ) const ; // is this a leap year? 22 bool endOfMonth( int ) const ; // is this end of month? Note difference between pre and post increment.
  62. 62. date1.h (2 of 2) 23 24 private : 25 int month; 26 int day; 27 int year; 28 29 static const int days[]; // array of days per month 30 void helpIncrement(); // utility function 31 32 }; // end class Date 33 34 #endif
  63. 63. date1.cpp (1 of 5) 1 // Fig. 8.11: date1.cpp 2 // Date class member function definitions. 3 #include <iostream> 4 #include &quot;date1.h&quot; 5 6 // initialize static member at file scope; 7 // one class-wide copy 8 const int Date::days[] = 9 { 0 , 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 }; 10 11 // Date constructor 12 Date::Date( int m, int d, int y ) 13 { 14 setDate( m, d, y ); 15 16 } // end Date constructor 17 18 // set month, day and year 19 void Date::setDate( int mm, int dd, int yy ) 20 { 21 month = ( mm >= 1 && mm <= 12 ) ? mm : 1 ; 22 year = ( yy >= 1900 && yy <= 2100 ) ? yy : 1900 ; 23
  64. 64. date1.cpp (2 of 5) 24 // test for a leap year 25 if ( month == 2 && leapYear( year ) ) 26 day = ( dd >= 1 && dd <= 29 ) ? dd : 1 ; 27 else 28 day = ( dd >= 1 && dd <= days[ month ] ) ? dd : 1 ; 29 30 } // end function setDate 31 32 // overloaded preincrement operator 33 Date &Date:: operator ++() 34 { 35 helpIncrement(); 36 37 return * this ; // reference return to create an lvalue 38 39 } // end function operator++ 40 41 // overloaded postincrement operator; note that the dummy 42 // integer parameter does not have a parameter name 43 Date Date:: operator ++( int ) 44 { 45 Date temp = * this ; // hold current state of object 46 helpIncrement(); 47 48 // return unincremented, saved, temporary object 49 return temp; // value return; not a reference return 50 51 } // end function operator++ Postincrement updates object and returns a copy of the original. Do not return a reference to temp, because it is a local variable that will be destroyed. Also note that the integer parameter does not have a name.
  65. 65. date1.cpp (3 of 5) 52 53 // add specified number of days to date 54 const Date &Date:: operator +=( int additionalDays ) 55 { 56 for ( int i = 0 ; i < additionalDays; i++ ) 57 helpIncrement(); 58 59 return * this ; // enables cascading 60 61 } // end function operator+= 62 63 // if the year is a leap year, return true; 64 // otherwise, return false 65 bool Date::leapYear( int testYear ) const 66 { 67 if ( testYear % 400 == 0 || 68 ( testYear % 100 != 0 && testYear % 4 == 0 ) ) 69 return true ; // a leap year 70 else 71 return false ; // not a leap year 72 73 } // end function leapYear 74
  66. 66. date1.cpp (4 of 5) 75 // determine whether the day is the last day of the month 76 bool Date::endOfMonth( int testDay ) const 77 { 78 if ( month == 2 && leapYear( year ) ) 79 return testDay == 29 ; // last day of Feb. in leap year 80 else 81 return testDay == days[ month ]; 82 83 } // end function endOfMonth 84 85 // function to help increment the date 86 void Date::helpIncrement() 87 { 88 // day is not end of month 89 if ( !endOfMonth( day ) ) 90 ++day; 91 92 else 93 94 // day is end of month and month < 12 95 if ( month < 12 ) { 96 ++month; 97 day = 1 ; 98 } 99
  67. 67. date1.cpp (5 of 5) 100 // last day of year 101 else { 102 ++year; 103 month = 1 ; 104 day = 1 ; 105 } 106 107 } // end function helpIncrement 108 109 // overloaded output operator 110 ostream & operator <<( ostream &output, const Date &d ) 111 { 112 static char *monthName[ 13 ] = { &quot;&quot; , &quot;January&quot; , 113 &quot;February&quot; , &quot;March&quot; , &quot;April&quot; , &quot;May&quot; , &quot;June&quot; , 114 &quot;July&quot; , &quot;August&quot; , &quot;September&quot; , &quot;October&quot; , 115 &quot;November&quot; , &quot;December&quot; }; 116 117 output << monthName[ d.month ] << ' ' 118 << d.day << &quot;, &quot; << d.year; 119 120 return output; // enables cascading 121 122 } // end function operator<<
  68. 68. fig08_12.cpp (1 of 2) 1 // Fig. 8.12: fig08_12.cpp 2 // Date class test program. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include &quot;date1.h&quot; // Date class definition 9 10 int main() 11 { 12 Date d1; // defaults to January 1, 1900 13 Date d2( 12 , 27 , 1992 ); 14 Date d3( 0 , 99 , 8045 ); // invalid date 15 16 cout << &quot;d1 is &quot; << d1 << &quot;nd2 is &quot; << d2 17 << &quot;nd3 is &quot; << d3; 18 19 cout << &quot;nnd2 += 7 is &quot; << ( d2 += 7 ); 20 21 d3.setDate( 2 , 28 , 1992 ); 22 cout << &quot;nn d3 is &quot; << d3; 23 cout << &quot;n++d3 is &quot; << ++d3; 24 25 Date d4( 7 , 13 , 2002 );
  69. 69. fig08_12.cpp (2 of 2) 26 27 cout << &quot;nnTesting the preincrement operator:n&quot; 28 << &quot; d4 is &quot; << d4 << 'n'; 29 cout << &quot;++d4 is &quot; << ++d4 << 'n' ; 30 cout << &quot; d4 is &quot; << d4; 31 32 cout << &quot;nnTesting the postincrement operator:n&quot; 33 << &quot; d4 is &quot; << d4 << 'n' ; 34 cout << &quot;d4++ is &quot; << d4++ << 'n' ; 35 cout << &quot; d4 is &quot; << d4 << endl; 36 37 return 0 ; 38 39 } // end main
  70. 70. fig08_12.cpp output (1 of 1) d1 is January 1, 1900 d2 is December 27, 1992 d3 is January 1, 1900 d2 += 7 is January 3, 1993 d3 is February 28, 1992 ++d3 is February 29, 1992 Testing the preincrement operator: d4 is July 13, 2002 ++d4 is July 14, 2002 d4 is July 14, 2002 Testing the postincrement operator: d4 is July 14, 2002 d4++ is July 14, 2002 d4 is July 15, 2002
  71. 71. 8.13 Standard Library Classes string and vector <ul><li>Classes built into C++ </li></ul><ul><ul><li>Available for anyone to use </li></ul></ul><ul><ul><li>string </li></ul></ul><ul><ul><ul><li>Similar to our String class </li></ul></ul></ul><ul><ul><li>vector </li></ul></ul><ul><ul><ul><li>Dynamically resizable array </li></ul></ul></ul><ul><li>Redo our String and Array examples </li></ul><ul><ul><li>Use string and vector </li></ul></ul>
  72. 72. 8.13 Standard Library Classes string and vector <ul><li>Class string </li></ul><ul><ul><li>Header <string>, namespace std </li></ul></ul><ul><ul><li>Can initialize string s1(“hi”); </li></ul></ul><ul><ul><li>Overloaded << </li></ul></ul><ul><ul><ul><li>cout << s1 </li></ul></ul></ul><ul><ul><li>Overloaded relational operators </li></ul></ul><ul><ul><ul><li>== != >= > <= < </li></ul></ul></ul><ul><ul><li>Assignment operator = </li></ul></ul><ul><ul><li>Concatenation (overloaded += ) </li></ul></ul>
  73. 73. 8.13 Standard Library Classes string and vector <ul><li>Class string </li></ul><ul><ul><li>Substring function substr </li></ul></ul><ul><ul><ul><li>s1.substr(0, 14); </li></ul></ul></ul><ul><ul><ul><ul><li>Starts at location 0, gets 14 characters </li></ul></ul></ul></ul><ul><ul><ul><li>S1.substr(15) </li></ul></ul></ul><ul><ul><ul><ul><li>Substring beginning at location 15 </li></ul></ul></ul></ul><ul><ul><li>Overloaded [] </li></ul></ul><ul><ul><ul><li>Access one character </li></ul></ul></ul><ul><ul><ul><li>No range checking (if subscript invalid) </li></ul></ul></ul><ul><ul><li>at function </li></ul></ul><ul><ul><ul><li>s1.at(10) </li></ul></ul></ul><ul><ul><ul><li>Character at subscript 10 </li></ul></ul></ul><ul><ul><ul><li>Has bounds checking </li></ul></ul></ul><ul><ul><ul><ul><li>Will end program if invalid (learn more in Chapter 13) </li></ul></ul></ul></ul>
  74. 74. fig08_13.cpp (1 of 4) 1 // Fig. 8.13: fig08_13.cpp 2 // Standard library string class test program. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include <string> 9 10 using std::string; 11 12 int main() 13 { 14 string s1( &quot;happy&quot; ); 15 string s2( &quot; birthday&quot; ); 16 string s3; 17 18 // test overloaded equality and relational operators 19 cout << &quot;s1 is &quot;&quot; << s1 << &quot;&quot;; s2 is &quot;&quot; << s2 20 << &quot;&quot;; s3 is &quot;&quot; << s3 << '&quot;' 21 << &quot;nnThe results of comparing s2 and s1:&quot; 22 << &quot;ns2 == s1 yields &quot; 23 << ( s2 == s1 ? &quot;true&quot; : &quot;false&quot; ) 24 << &quot;ns2 != s1 yields &quot; 25 << ( s2 != s1 ? &quot;true&quot; : &quot;false&quot; )
  75. 75. fig08_13.cpp (2 of 4) 26 << &quot;ns2 > s1 yields &quot; 27 << ( s2 > s1 ? &quot;true&quot; : &quot;false&quot; ) 28 << &quot;ns2 < s1 yields &quot; 29 << ( s2 < s1 ? &quot;true&quot; : &quot;false&quot; ) 30 << &quot;ns2 >= s1 yields &quot; 31 << ( s2 >= s1 ? &quot;true&quot; : &quot;false&quot; ) 32 << &quot;ns2 <= s1 yields &quot; 33 << ( s2 <= s1 ? &quot;true&quot; : &quot;false&quot; ); 34 35 // test string member function empty 36 cout << &quot;nnTesting s3.empty():n&quot; ; 37 38 if ( s3.empty() ) { 39 cout << &quot;s3 is empty; assigning s1 to s3;n&quot; ; 40 s3 = s1; // assign s1 to s3 41 cout << &quot;s3 is &quot;&quot; << s3 << &quot;&quot;&quot; ; 42 } 43 44 // test overloaded string concatenation operator 45 cout << &quot;nns1 += s2 yields s1 = &quot; ; 46 s1 += s2; // test overloaded concatenation 47 cout << s1; 48
  76. 76. fig08_13.cpp (3 of 4) 49 // test overloaded string concatenation operator 50 // with C-style string 51 cout << &quot;nns1 += &quot; to you&quot; yieldsn&quot; ; 52 s1 += &quot; to you&quot; ; 53 cout << &quot;s1 = &quot; << s1 << &quot;nn&quot; ; 54 55 // test string member function substr 56 cout << &quot;The substring of s1 starting at location 0 forn&quot; 57 << &quot;14 characters, s1.substr(0, 14), is:n&quot; 58 << s1.substr( 0 , 14 ) << &quot;nn&quot; ; 59 60 // test substr &quot;to-end-of-string&quot; option 61 cout << &quot;The substring of s1 starting atn&quot; 62 << &quot;location 15, s1.substr(15), is:n&quot; 63 << s1.substr( 15 ) << 'n' ; 64 65 // test copy constructor 66 string *s4Ptr = new string( s1 ); 67 cout << &quot;n*s4Ptr = &quot; << *s4Ptr << &quot;nn&quot; ; 68 69 // test assignment (=) operator with self-assignment 70 cout << &quot;assigning *s4Ptr to *s4Ptrn&quot; ; 71 *s4Ptr = *s4Ptr; 72 cout << &quot;*s4Ptr = &quot; << *s4Ptr << 'n' ; 73
  77. 77. fig08_13.cpp (4 of 4) 74 // test destructor 75 delete s4Ptr; 76 77 // test using subscript operator to create lvalue 78 s1[ 0 ] = 'H' ; 79 s1[ 6 ] = 'B' ; 80 cout << &quot;ns1 after s1[0] = 'H' and s1[6] = 'B' is: &quot; 81 << s1 << &quot;nn&quot; ; 82 83 // test subscript out of range with string member function &quot;at&quot; 84 cout << &quot;Attempt to assign 'd' to s1.at( 30 ) yields:&quot; << endl; 85 s1.at( 30 ) = 'd'; // ERROR: subscript out of range 86 87 return 0 ; 88 89 } // end main
  78. 78. fig08_13.cpp output (1 of 2) s1 is &quot;happy&quot;; s2 is &quot; birthday&quot;; s3 is &quot;&quot;   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.empty(): s3 is empty; assigning s1 to s3; s3 is &quot;happy&quot;   s1 += s2 yields s1 = happy birthday   s1 += &quot; to you&quot; yields s1 = happy birthday to you   The substring of s1 starting at location 0 for 14 characters, s1.substr(0, 14), is: happy birthday  
  79. 79. fig08_13.cpp output (2 of 2) The substring of s1 starting at location 15, s1.substr(15), is: to you   *s4Ptr = happy birthday to you   assigning *s4Ptr to *s4Ptr *s4Ptr = happy birthday to you   s1 after s1[0] = 'H' and s1[6] = 'B' is: Happy Birthday to you Attempt to assign 'd' to s1.at( 30 ) yields:   abnormal program termination
  80. 80. 8.13 Standard Library Classes string and vector <ul><li>Class vector </li></ul><ul><ul><li>Header <vector> , namespace std </li></ul></ul><ul><ul><li>Store any type </li></ul></ul><ul><ul><ul><li>vector< int > myArray(10) </li></ul></ul></ul><ul><ul><li>Function size ( myArray.size() ) </li></ul></ul><ul><ul><li>Overloaded [] </li></ul></ul><ul><ul><ul><li>Get specific element, myArray[3] </li></ul></ul></ul><ul><ul><li>Overloaded != , == , and = </li></ul></ul><ul><ul><ul><li>Inequality, equality, assignment </li></ul></ul></ul>
  81. 81. fig08_14.cpp (1 of 5) 1 // Fig. 8.14: fig08_14.cpp 2 // Demonstrating standard library class vector. 3 #include <iostream> 4 5 using std::cout; 6 using std::cin; 7 using std::endl; 8 9 #include <iomanip> 10 11 using std::setw; 12 13 #include <vector> 14 15 using std::vector; 16 17 void outputVector( const vector< int > & ); 18 void inputVector( vector< int > & ); 19 20 int main() 21 { 22 vector< int > integers1( 7 ); // 7-element vector< int > 23 vector< int > integers2( 10 ); // 10-element vector< int > 24
  82. 82. fig08_14.cpp (2 of 5) 25 // print integers1 size and contents 26 cout << &quot;Size of vector integers1 is &quot; 27 << integers1.size() 28 << &quot;nvector after initialization:n&quot; ; 29 outputVector( integers1 ); 30 31 // print integers2 size and contents 32 cout << &quot;nSize of vector integers2 is &quot; 33 << integers2.size() 34 << &quot;nvector after initialization:n&quot; ; 35 outputVector( integers2 ); 36 37 // input and print integers1 and integers2 38 cout << &quot;nInput 17 integers:n&quot; ; 39 inputVector( integers1 ); 40 inputVector( integers2 ); 41 42 cout << &quot;nAfter input, the vectors contain:n&quot; 43 << &quot;integers1:n&quot; ; 44 outputVector( integers1 ); 45 cout << &quot;integers2:n&quot; ; 46 outputVector( integers2 ); 47 48 // use overloaded inequality (!=) operator 49 cout << &quot;nEvaluating: integers1 != integers2n&quot; ; 50
  83. 83. fig08_14.cpp (3 of 5) 51 if ( integers1 != integers2 ) 52 cout << &quot;integers1 and integers2 are not equaln&quot; ; 53 54 // create vector integers3 using integers1 as an 55 // initializer; print size and contents 56 vector< int > integers3( integers1 ); // copy constructor 57 58 cout << &quot;nSize of vector integers3 is &quot; 59 << integers3.size() 60 << &quot;nvector after initialization:n&quot; ; 61 outputVector( integers3 ); 62 63 64 // use overloaded assignment (=) operator 65 cout << &quot;nAssigning integers2 to integers1:n&quot; ; 66 integers1 = integers2; 67 68 cout << &quot;integers1:n&quot; ; 69 outputVector( integers1 ); 70 cout << &quot;integers2:n&quot; ; 71 outputVector( integers1 ); 72
  84. 84. fig08_14.cpp (4 of 5) 73 // use overloaded equality (==) operator 74 cout << &quot;nEvaluating: integers1 == integers2n&quot; ; 75 76 if ( integers1 == integers2 ) 77 cout << &quot;integers1 and integers2 are equaln&quot; ; 78 79 // use overloaded subscript operator to create rvalue 80 cout << &quot;nintegers1[5] is &quot; << integers1[ 5 ]; 81 82 // use overloaded subscript operator to create lvalue 83 cout << &quot;nnAssigning 1000 to integers1[5]n&quot; ; 84 integers1[ 5 ] = 1000 ; 85 cout << &quot;integers1:n&quot; ; 86 outputVector( integers1 ); 87 88 // attempt to use out of range subscript 89 cout << &quot;nAttempt to assign 1000 to integers1.at( 15 )&quot; 90 << endl; 91 integers1.at( 15 ) = 1000; // ERROR: out of range 92 93 return 0 ; 94 95 } // end main 96
  85. 85. fig08_14.cpp (5 of 5) 97 // output vector contents 98 void outputVector( const vector< int > &array ) 99 { 100 for ( int i = 0 ; i < array.size(); i++ ) { 101 cout << setw( 12 ) << array[ i ]; 102 103 if ( ( i + 1 ) % 4 == 0 ) // 4 numbers per row of output 104 cout << endl; 105 106 } // end for 107 108 if ( i % 4 != 0 ) 109 cout << endl; 110 111 } // end function outputVector 112 113 // input vector contents 114 void inputVector( vector< int > &array ) 115 { 116 for ( int i = 0 ; i < array.size(); i++ ) 117 cin >> array[ i ]; 118 119 } // end function inputVector
  86. 86. fig08_14.cpp output (1 of 2) Size of vector integers1 is 7 vector after initialization: 0 0 0 0 0 0 0   Size of vector integers2 is 10 vector 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 vectors contain: integers1: 1 2 3 4 5 6 7 integers2: 8 9 10 11 12 13 14 15 16 17   Evaluating: integers1 != integers2 integers1 and integers2 are not equal
  87. 87. fig08_14.cpp output (2 of 2) Size of vector integers3 is 7 vector after initialization: 1 2 3 4 5 6 7   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   Evaluating: integers1 == integers2 integers1 and integers2 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.at( 15 )   abnormal program termination

×