1 Chapter 8 - Operator Overloading Outline 8.1Introduction 8.2Fundamentals of Operator Overloading 8.3Restrictions on Operator Overloading 8.4Operator.

Slides:



Advertisements
Similar presentations
Chapter 11 Operator Overloading; String and Array Objects Chapter 11 Operator Overloading; String and Array Objects Part I.
Advertisements

Operator Overloading. Introduction Operator overloading –Enabling C++’s operators to work with class objects –Using traditional operators with user-defined.
 2003 Prentice Hall, Inc. All rights reserved. 1 Chapter 8 - Operator Overloading Outline 8.1 Introduction 8.2 Fundamentals of Operator Overloading 8.3.
Operator Overloading Fundamentals
Operator Overloading. Basics Define operations on user-defined data types –Perform same operation as it is supposed to but, with operands of the user-defined.
 2006 Pearson Education, Inc. All rights reserved Operator Overloading.
© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. Chapter 18 - C++ Operator Overloading Outline 18.1Introduction.
Operator Overloading in C++ Systems Programming. Systems Programming: Operator Overloading 22   Fundamentals of Operator Overloading   Restrictions.
 2000 Prentice Hall, Inc. All rights reserved. Chapter 18 - Operator Overloading Outline 18.1Introduction 18.2Fundamentals of Operator Overloading 18.3Restrictions.
 2006 Pearson Education, Inc. All rights reserved Operator Overloading; String and Array Objects.
8.1 Introduction Use operators with objects (operator overloading) –Clearer than function calls for certain classes –Operator sensitive to context Examples.
 2008 Pearson Education, Inc. All rights reserved Operator Overloading; String and Array Objects.
Operator OverloadingCS-2303, C-Term Operator Overloading CS-2303 System Programming Concepts (Slides include materials from The C Programming Language,
Operator overloading Object Oriented Programming.
Operator Overloading in C++
Review of C++ Programming Part II Sheng-Fang Huang.
C++ Programming: Program Design Including Data Structures, Fourth Edition Chapter 14: Overloading and Templates.
 2003 Prentice Hall, Inc. All rights reserved. 1 Chapter 8 - Operator Overloading Outline 8.1Introduction 8.2Fundamentals of Operator Overloading 8.3Restrictions.
Chapter 18 - Operator Overloading Associate Prof. Yuh-Shyan Chen Dept. of Computer Science and Information Engineering National Chung-Cheng University.
 2006 Pearson Education, Inc. All rights reserved Classes: A Deeper Look.
C++ Programming: From Problem Analysis to Program Design, Fourth Edition Chapter 15: Overloading and Templates.
 2003 Prentice Hall, Inc. All rights reserved. 1 Chapter 8: Operator Overloading Outline 8.1Introduction 8.2Const (Constant) Objects and const Member.
 2006 Pearson Education, Inc. All rights reserved Classes: A Deeper Look, Part 2.
 2006 Pearson Education, Inc. All rights reserved Operator Overloading; String and Array Objects.
Operator Overloading Operator Overloading allows a programmer to define new uses of the existing C/C++ operator symbols. –useful for defining common operations.
Overloading Operator MySting Example. Operator Overloading 1+2 Matrix M 1 + M 2 Using traditional operators with user-defined objects More convenient.
C++ How to Program, 7/e © by Pearson Education, Inc. All Rights Reserved.
 2008 Pearson Education, Inc. All rights reserved Operator Overloading.
Chapter 11 Friends and Overloaded Operators. Introduction to function equal // Date.h #ifndef _DATE_H_ #define _DATE_H_ class CDate { public: CDate();
 2003 Prentice Hall, Inc. All rights reserved. 1 Chapter 8 - Operator Overloading Outline 8.1Introduction 8.2Fundamentals of Operator Overloading 8.3Restrictions.
CS Object Oriented Programming Using C++
 2003 Prentice Hall, Inc. All rights reserved. ECE 2552 Dr. Veton Këpuska Based on Dr. S. Kozaitis Summer 2003 Slides. 1 Chapter 8 - Operator Overloading.
1 CISC181 Introduction to Computer Science Dr. McCoy Lecture 25 December 1, 2009.
 2003 Prentice Hall, Inc. All rights reserved. 1 Chapter 8: Operator Overloading Outline 8.1Introduction 8.2Fundamentals of Operator Overloading 8.3Restrictions.
1 Overloading  Functions overloading  Operator overloading.
 2000 Deitel & Associates, Inc. All rights reserved. Chapter 8 - Operator Overloading Outline 8.1Introduction 8.2Fundamentals of Operator Overloading.
Learning Objectives Fundamentals of Operator Overloading. Restrictions of Operator Overloading. Global and member Operator. Overloading Stream-Insertion.
1 CISC181 Introduction to Computer Science Dr. McCoy Lecture 26 Clicker Questions December 3, 2009.
 2000 Prentice Hall, Inc. All rights reserved. 1 Chapter 8 - Operator Overloading Outline 8.1Introduction 8.2Fundamentals of Operator Overloading 8.3Restrictions.
Dale Roberts Operator Overloading Dale Roberts, Lecturer Computer Science, IUPUI Department of Computer and Information Science,
 2008 Pearson Education, Inc. All rights reserved Operator Overloading; String and Array Objects.
 2003 Prentice Hall, Inc. All rights reserved. 1 IS 0020 Program Design and Software Tools Introduction to C++ Programming Review slides Mar 15, 2005.
 2006 Pearson Education, Inc. All rights reserved Operator Overloading; String and Array Objects.
Operator Overloading.
Chapter 18 - C++ Operator Overloading
Chapter 10 Operator Overloading; Class string
IS Program Design and Software Tools Introduction to C++ Programming
Department of Computer and Information Science, School of Science, IUPUI Operator Overloading Dale Roberts, Lecturer Computer Science, IUPUI
Operator Overloading; String and Array Objects
Overloading Operator MySting Example
Operator Overloading; Class string
Chapter 11 - Operator Overloading
Polymorphism in C++ Operator Overloading
Operator Overloading; String and Array Objects
Operator Overloading.
Chapter 8 - Operator Overloading
Operator Overloading; String and Array Objects
Chapter 8 - Operator Overloading
Use operators with objects (operator overloading)
Operator Overloading.
Operator Overloading; String and Array Objects
Operator Overloading Professor Hugh C. Lauer CS-2303, System Programming Concepts (Slides include materials from The C Programming Language, 2nd edition,
9-10 Classes: A Deeper Look.
Recitation Course 0603 Speaker: Liu Yu-Jiun.
Operator Overloading; String and Array Objects
Chapter 18 - Operator Overloading
Chapter 8 - Operator Overloading
Operator Overloading; String and Array Objects
9-10 Classes: A Deeper Look.
Presentation transcript:

1 Chapter 8 - Operator Overloading Outline 8.1Introduction 8.2Fundamentals of Operator Overloading 8.3Restrictions on Operator Overloading 8.4Operator Functions as Class Members vs. as friend Functions 8.5Overloading Stream-Insertion and Stream-Extraction Operators 8.6Overloading Unary Operators 8.7Overloading Binary Operators 8.8Case Study: Array Class 8.9 Converting between Types 8.10Case Study: A String Class 8.11Overloading ++ and Case Study: A Date Class

2 8.1 Introduction Use operators with objects (operator overloading) –Clearer than function calls for certain classes –Operator sensitive to context Examples –<< Stream insertion, bitwise left-shift –+ Performs arithmetic on multiple types (integers, floats, etc.) Will discuss when to use operator overloading

3 8.2 Fundamentals of Operator Overloading Object Types –Built in ( int, char ) or user-defined –Can use existing operators with user-defined types Cannot create new operators Overloading operators –Create a function for the class –Name function operator followed by symbol operator+ for the addition operator +

4 8.2 Fundamentals of Operator Overloading Using operators on a class object –It must be overloaded for that class, with two exceptions Assignment operator, = –Memberwise assignment between objects Address operator, & –Returns address of object Both can be overloaded Overloading provides concise notation object1.add(object2); object2.operator+(object1); object2 + object1;

5 8.3 Restrictions on Operator Overloading Cannot change –How operators act on built-in data types i.e., cannot change integer addition –Precedence of operator (order of evaluation) Use parentheses to force order-of-operations –Associativity (left-to-right or right-to-left) –Number of operands & is unitary, only acts on one operand Cannot create new operators Operators must be overloaded explicitly –Overloading + does not overload +=

6 Operator Summary ::Binary (unary) scope operator () []Array subscript.Member selection via object ->Member selection via pointer ++, --Unary post-increment, post-decrement +, -, !Unary plus, minus, logical negation &, *Address, deference new, new[]Dynamic memory, array allocation delete, delete[]Dynamic memory, array de-allocation *, /, %Multiplication, division, modulus +, -Addition, subtraction

7 Operator Summary >Stream insertion, extraction operator, >=Relational less, less or equal, greater, greater or equal operator ==. !=Relational is equal to, not equal to &&, ||Logical AND, OR ?:Ternary condition =Assignment +=, -=addition, subtraction assignment *=,/=,%=multiplication, division, modulus

8 8.3 Restrictions on Operator Overloading

9 File Number.h // Number.h #ifndef NUMBER_H #define NUMBER_H class Number { public: Number() { x = 0; } Number( int x ); int getValue() { return x; } Number operator+( const Number& ) const; Number operator-() const; Number& operator=( const Number& ); private: int x; }; #endif

10 File Number.cpp // Number.cpp #include "Number.h" Number::Number( int x ) { this->x = x; } Number Number::operator+( const Number& b ) const { return Number(x + (b.x)); } Number Number::operator-() const { return Number(-x); } Number& Number::operator=( const Number& b ) { x = b.x; return *this; } X=5 b X=4X=9 Number X=5X=-5 Number X=9 b *this

11 Test Client (1) // Test Client #include using namespace std; #include "Number.h" int main() { Number a = Number( 3 ); Number b = Number( 4 ); Number c = Number( 5 ); cout << a.getValue() <<","<< b.getValue() <<","<< c.getValue() << endl; a = b.operator+( c ); cout << a.getValue() <<","<< b.getValue() <<","<< c.getValue() << endl; a = b + c; cout << a.getValue() <<","<< b.getValue() <<","<< c.getValue() << endl; X=3X=4 ab X=5 c

12 Test Client (2) b = c.operator-(); cout << a.getValue() <<","<< b.getValue() <<","<< c.getValue() << endl; b = -c; cout << a.getValue() <<","<< b.getValue() <<","<< c.getValue() << endl; return 0; } X=3X=4 ab X=5 c

Operator Functions As Class Members Vs. As Friend Functions Operator functions –Member functions Use this keyword to implicitly obtain one of their arguments Leftmost operand must be of an object of the operator’s class Gets left operand for binary operators (like + ) –Non member functions Need parameters for both operands of a binary operator Can have object of different class or a built-in type Must be a friend to access private or protected data Other operators except (), [], -> and assignment operator –Called when Left operand of binary operator of same class Single operand of unitary operator of same class

Operator Functions As Class Members Vs. As Friend Functions Commutative operators –May want + to be commutative So both “ a + b ” and “ b + a ” work –Suppose we have two different classes Overloaded operator can only be member function when its class is on left longint number, HugeIntClass bigInteger bigInteger + number number.operator+( bigInteger); –Can be member function When other way, need a non-member overload function number + bigInteger operator+( number, bigInteger);

Operator Functions As Class Members Vs. As Friend Functions Overloaded << operator –Left operand of type ostream & cout << classObject operator<<( cout, classObject) –Similarly, overloaded >> needs istream & as left operand operator>>( cin, classObject) –Thus, both must be non-member functions friend ostream &operator<<( ostream&, const classObject & ); friend istream &operator>>( istream&, classObject & );

Overloading Unary Operators Overloading unary operators –Non- static member function, no arguments –Non-member function, one argument Argument must be class object or reference to class object –Remember, static functions only access static data –Operators ~, !, *, & –Example !object1 is interpreted as operator!(object1)

17 Upcoming example (8.10 String class) Overload ! to test for empty string If non- static member function, needs no arguments !s becomes s.operator!() class String { public: bool operator!() const;... }; bool String::operator!() const { return length == 0; }... String s1( "happy" ); String s3; if ( !s3 ) {...}

18 Upcoming example If non-member function, needs one argument s! becomes operator!(s) class String { friend bool operator!( const String & );... }... bool operator!( const String & s ) const { return s.length == 0; }... String s1( "happy" ); String s3; if ( s3! ) {... }

Overloading Binary Operators Overloading binary operators –Non- static member function, one argument –Non-member function, two arguments One argument must be class object or reference –Operators +,-,*,/,>,<,==,…… –Example object1 + object2 is interpreted as object1. operator+(object2)

20 Upcoming example(8.10 String class) class String { public: bool operator==( const String &right ) const; bool operator!=( const String &right ) const { return !( *this == right ); } bool operator<( const String &right ) const bool operator>( const String &right ) const { return right < *this; } const String &operator+=( const String & ); }; bool String::operator==( const String &right ) const { return strcmp( sPtr, right.sPtr ) == 0; } bool String::operator<( const String &right ) const{ return strcmp( sPtr, right.sPtr ) < 0; }

21 Upcoming example(8.10 String class) const String & String:: operator+=( const String &right ){ size_t newLength = length + right.length; char *tempPtr = new char[ newLength + 1 ]; strcpy( tempPtr, sPtr ); strcpy( tempPtr + length, right.sPtr ); delete [] sPtr; sPtr = tempPtr; length = newLength; return *this; }

22 Upcoming example(8.10 String class) –y += z equivalent to y.operator+=( z ) –( s2 != s1) –( s2 > s1),( s2 < s1) –( s2 >= s1),( s2 <= s1) –s3 = s1 –s1 += s2

23 Upcoming example If non-member function, needs two arguments Example: class String { friend const String &operator+=( String &, const String & );... }; y += z equivalent to operator+=( y, z )

24 Upcoming example(8.8 Array class) class Array { public: const Array &operator=( const Array & ); bool operator==( const Array & ) const; bool operator!=( const Array &right ) const { return ! ( *this == right ); }... }... bool Array::operator==( const Array &right ) const { if ( size != right.size ) return false; for ( int i = 0; i < size; i++ ) if ( ptr[ i ] != right.ptr[ i ] ) return false; return true; }

25 Upcoming example(8.8 Array class) const Array &Array::operator=( const Array &right ) { if ( &right != this ) { if ( size != right.size ) { delete [] ptr; size = right.size; ptr = new int[ size ]; } for ( int i = 0; i < size; i++ ) ptr[ i ] = right.ptr[ i ]; } return *this; }... Array integers1( 7 ); Array integers2; Array integers3( integers1 ); integers1 = integers2;... if ( integers1 == integers2 )...

26 Upcoming example(8.12 Date class)

27 Overloaded << operator Left operand of type ostream & cout << classObject operator<<( cout, classObject) Similarly, overloaded >> needs istream & as left operand operator>>( cin, classObject) Thus, both must be non-member functions friend ostream &operator<<( ostream&, const classObject & ); friend istream &operator>>( istream&, classObject & );

Overloading Stream-Insertion and Stream-Extraction Operators > –Already overloaded to process each built-in type –Can also process a user-defined class Example program –Class PhoneNumber Holds a telephone number –Print out formatted number automatically (123)

29 fig08_03.cpp (1 of 3) 1 // Fig. 8.3: fig08_03.cpp 17 class PhoneNumber { 18 friend ostream &operator<<( ostream&, const PhoneNumber & ); 19 friend istream &operator>>( istream&, PhoneNumber & ); 21 private: 22 char areaCode[ 4 ]; 23 char exchange[ 4 ]; 24 char line[ 5 ]; 26 }; 31 ostream &operator<<( ostream &output, const PhoneNumber &num ){ 33 output << "(" << num.areaCode << ") " 34 << num.exchange << "-" << num.line; 36 return output; 38 } 43 istream &operator>>( istream &input, PhoneNumber &num ){ 45 input.ignore(); 46 input >> setw( 4 ) >> num.areaCode; 47 input.ignore( 2 ); 48 input >> setw( 4 ) >> num.exchange; 49 input.ignore(); 50 input >> setw( 5 ) >> num.line; 52 return input; 54 }

30 fig08_03.cpp (3 of 3) fig08_03.cpp output (1 of 1) 56 int main() { 58 PhoneNumber phone; 60 cout << "Enter phone number in the form (123) :\n"; 64 cin >> phone; 66 cout << "The phone number entered was: " ; 70 cout << phone << endl; 72 return 0; 74 } Enter phone number in the form (123) : (800) The phone number entered was: (800)

Case Study: Array class Arrays in C++ –No range checking –Cannot be compared meaningfully with == –No array assignment (array names const pointers) –Cannot input/output entire arrays at once One element at a time Example:Implement an Array class with –Range checking –Array assignment –Arrays that know their size –Outputting/inputting entire arrays with > –Array comparisons with == and !=

Case Study: Array class Copy constructor –Used whenever copy of object needed Passing by value (return value or parameter) Initializing an object with a copy of another –Array newArray( oldArray ); –newArray copy of oldArray –Prototype for class Array Array( const Array & ); Must take reference –Otherwise, pass by value –Tries to make copy by calling copy constructor… –Infinite loop

33 array1.h (1 of 2) 1 // Fig. 8.4: array1.h …… 11 class Array { 12 friend ostream &operator<<( ostream &, const Array & ); 13 friend istream &operator>>( istream &, Array & ); 15 public: 16 Array( int = 10 ); 17 Array( const Array & ); 18 ~Array(); 19 int getSize() const; 22 const Array &operator=( const Array & ); 25 bool operator==( const Array & ) const; 28 bool operator!=( const Array &right ) const { 30 return ! ( *this == right ); 32 } 35 int &operator[]( int ); 38 const int &operator[]( int ) const; 40 private: 41 int size; 42 int *ptr; 44 }; ……

34 array1.cpp (1 of 7) 1 // Fig 8.5: array1.cpp 13 #include 15 #include 17 #include "array1.h" 20 Array::Array( int arraySize ) { 23 size = ( arraySize > 0 ? arraySize : 10 ); 25 ptr = new int[ size ]; 27 for ( int i = 0; i < size; i++ ) 28 ptr[ i ] = 0; 30 } Array::Array( const Array &arrayToCopy ) 35 : size( arrayToCopy.size ) { 37 ptr = new int[ size ]; 39 for ( int i = 0; i < size; i++ ) 40 ptr[ i ] = arrayToCopy.ptr[ i ]; 42 } Array::~Array() { 47 delete [] ptr; 49 }

35 52 int Array::getSize() const { 54 return size; 56 } 60 const Array &Array::operator=( const Array &right ) { 62 if ( &right != this ) { 66 if ( size != right.size ) { 67 delete [] ptr; 68 size = right.size; 69 ptr = new int[ size ]; 71 } 73 for ( int i = 0; i < size; i++ ) 74 ptr[ i ] = right.ptr[ i ]; 76 } 78 return *this; 80 } 84 bool Array::operator==( const Array &right ) const { 86 if ( size != right.size ) 87 return false; 89 for ( int i = 0; i < size; i++ ) 91 if ( ptr[ i ] != right.ptr[ i ] ) 92 return false; 94 return true; 96 }

36 array1.cpp (5 of 7) 100 int &Array::operator[]( int subscript ) { 103 if ( subscript = size ) { 104 cout << "\nError: Subscript " << subscript 105 << " out of range" << endl; 107 exit( 1 ); 109 } 111 return ptr[ subscript ]; 113 } 117 const int &Array::operator[]( int subscript ) const { 120 if ( subscript = size ) { 121 cout << "\nError: Subscript " << subscript 122 << " out of range" << endl; 124 exit( 1 ); 126 } 128 return ptr[ subscript ]; 130 } istream &operator>>( istream &input, Array &a ) { 136 for ( int i = 0; i < a.size; i++ ) 137 input >> a.ptr[ i ]; 139 return input; // enables cin >> x >> y; 141 }

37 array1.cpp (7 of 7) 144 ostream &operator<<( ostream &output, const Array &a ) 145 { 146 int i; for ( i = 0; i < a.size; i++ ) { 150 output << setw( 12 ) << a.ptr[ i ]; if ( ( i + 1 ) % 4 == 0 ) // 4 numbers per row of output 153 output << endl; 155 } 157 if ( i % 4 != 0 ) 158 output << endl; 160 return output; // enables cout << x << y; 162 }

38 fig08_06.cpp (1 of 3) 1 // Fig. 8.6: fig08_06.cpp 9 #include "array1.h" 11 int main() { 13 Array integers1( 7 ); 14 Array integers2; 17 cout << integers1.getSize() << integers1; 22 cout << integers2.getSize() << integers2; 28 cin >> integers1 >> integers2; 30 cout << integers1 << integers2; 37 if ( integers1 != integers2 ) 38 cout << "integers1 and integers2 are not equal\n"; 42 Array integers3( integers1 ); 44 cout << integers3.getSize() << integers3; 50 integers1 = integers2; 52 cout << integers1 << integers2; 58 if ( integers1 == integers2 ) 59 cout << "integers1 and integers2 are equal\n"; 62 cout << integers1[ 5 ]; 66 integers1[ 5 ] = 1000; 67 cout << integers1; 71 integers1[ 15 ] = 1000; // ERROR: out of range 73 return 0; 75 }

39 fig08_06.cpp output (1 of 3) Size of array integers1 is 7 Array after initialization: Size of array integers2 is 10 Array after initialization: Input 17 integers: After input, the arrays contain: integers1: integers2:

40 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: Assigning integers2 to integers1: integers1: integers2: Evaluating: integers1 == integers2 integers1 and integers2 are equal integers1[5] is 13

41 fig08_06.cpp output (3 of 3) Assigning 1000 to integers1[5] integers1: Attempt to assign 1000 to integers1[15] Error: Subscript 15 out of range

Converting between Types Casting –Traditionally, cast integers to floats, etc. –May need to convert between user-defined types Cast operator (conversion operator) –Convert from One class to another Class to built-in type ( int, char, etc.) –Must be non- static member function Cannot be friend –Do not specify return type Implicitly returns type to which you are converting

Converting between Types Example –Prototype A::operator char *() const; Casts class A to a temporary char * (char *)s calls s.operator char*() –Also A::operator int() const; A::operator OtherClass() const;

Converting between Types Casting can prevent need for overloading –Suppose class String can be cast to char * –cout << s; // s is a String Compiler implicitly converts s to char * Do not have to overload << –Compiler can only do 1 cast

Case Study: A String Class Build class String –String creation, manipulation –Class string in standard library (more 8.13, Chapter 15) Conversion constructor –Single-argument constructor –Turns objects of other types into class objects String s1(“hi”); Creates a String from a char * –Any single-argument constructor is a conversion constructor

46 string1.h (1 of 3) 1 // Fig. 8.7: string1.h …… 11 class String { 12 friend ostream &operator<<( ostream &, const String & ); 13 friend istream &operator>>( istream &, String & ); 15 public: 16 String( const char * = "" ); 17 String( const String & ); 18 ~String(); 20 const String &operator=( const String & ); 21 const String &operator+=( const String & ); 23 bool operator!() const; 24 bool operator==( const String & ) const; 25 bool operator<( const String & ) const; 28 bool operator!=( const String & right ) const { 30 return !( *this == right ); 32 } 35 bool operator>( const String &right ) const { 37 return right < *this; 39 }

47 string1.h (2 of 3) 42 bool operator<=( const String &right ) const { 44 return !( right < *this ); 46 } 49 bool operator>=( const String &right ) const { 51 return !( *this < right ); 53 } 55 char &operator[]( int ); 56 const char &operator[]( int ) const; 58 String operator()( int, int ); 60 int getLength() const; 62 private: 63 int length; 64 char *sPtr; 66 void setString( const char * ); 68 }; 70 #endif

48 string1.cpp (1 of 8) 1 // Fig. 8.8: string1.cpp String::String( const char *s ) : length( strlen( s ) ) { 23 cout << "Conversion constructor: " << s << '\n'; 24 setString( s ); 26 } 29 String::String( const String &copy ) : length( copy.length ) { 32 cout << "Copy constructor: " << copy.sPtr << '\n'; 33 setString( copy.sPtr ); 35 } 38 String::~String() { 40 cout << "Destructor: " << sPtr << '\n'; 41 delete [] sPtr; 43 } 46 const String &String::operator=( const String &right ) { 48 cout << "operator= called\n"; 50 if ( &right != this ) { 51 delete [] sPtr; 52 length = right.length; 53 setString( right.sPtr ); 54 } 56 else 57 cout << "Attempted assignment of a String to itself\n"; 59 return *this; 61 }

49 string1.cpp (3 of 8) 65 const String &String::operator+=( const String &right ) { 67 size_t newLength = length + right.length; 68 char *tempPtr = new char[ newLength + 1 ]; strcpy( tempPtr, sPtr ); 71 strcpy( tempPtr + length, right.sPtr ); delete [] sPtr; 74 sPtr = tempPtr; 75 length = newLength; 77 return *this; 79 } 82 bool String::operator!() const { 84 return length == 0; 86 } 89 bool String::operator==( const String &right ) const { 91 return strcmp( sPtr, right.sPtr ) == 0; 93 } 96 bool String::operator<( const String &right ) const{ 98 return strcmp( sPtr, right.sPtr ) < 0; 100 }

50 string1.cpp (5 of 8) 103 char &String::operator[]( int subscript ) { 106 if ( subscript = length ) { 107 cout << "Error: Subscript " << subscript 108 << " out of range" << endl; 110 exit( 1 ); 111 } 113 return sPtr[ subscript ]; 115 } 118 const char &String::operator[]( int subscript ) const { 121 if ( subscript = length ) { 122 cout << "Error: Subscript " << subscript 123 << " out of range" << endl; 125 exit( 1 ); 126 } 128 return sPtr[ subscript ]; 130 }

51 string1.cpp (6 of 8) 134 String String::operator()( int index, int subLength ) { 138 if ( index = length || subLength < 0 ) 139 return ""; // converted to a String object automatically int len; if ( ( subLength == 0 ) || ( index + subLength > length ) ) 145 len = length - index; 146 else 147 len = subLength; char *tempPtr = new char[ len + 1 ]; strncpy( tempPtr, &sPtr[ index ], len ); 155 tempPtr[ len ] = '\0'; 158 String tempString( tempPtr ); 159 delete [] tempPtr; // delete temporary array 161 return tempString; // return copy of the temporary String 163 }

52 string1.cpp (7 of 8) 166 int String::getLength() const { 168 return length; 170 } void String::setString( const char *string2 ) { 175 sPtr = new char[ length + 1 ]; 176 strcpy( sPtr, string2 ); 178 } 181 ostream &operator<<( ostream &output, const String &s ) { 183 output << s.sPtr; 185 return output; // enables cascading 187 } 190 istream &operator>>( istream &input, String &s ) 191 { 192 char temp[ 100 ]; // buffer to store input 194 input >> setw( 100 ) >> temp; 195 s = temp; 197 return input; // enables cascading 199 }

53 fig08_09.cpp (1 of 4) 1 // Fig. 8.9: fig08_09.cpp …… 8 #include "string1.h" 10 int main() { 12 String s1( "happy" ); 13 String s2( " birthday" ); 14 String s3; 17 cout << s1 << s2<< s3 21 << ( s2 == s1 ? "true" : "false" ) 22 << ( s2 != s1 ? "true" : "false" ) 24 s1 ? "true" : "false" ) 27 << ( s2 < s1 ? "true" : "false" ) 28 = s1 ? "true" : "false" ) 30 << ( s2 <= s1 ? "true" : "false" ); 36 if ( !s3 ) { 38 s3 = s1; 39 cout << s3; 40 } 44 s1 += s2; 45 cout << s1; 49 s1 += " to you"; 50 cout << s1;

54 fig08_09.cpp (3 of 4) 53 cout << s1( 0, 14 ) << "\n\n"; 58 cout << s1( 15, 0 ) << "\n\n"; 63 String *s4Ptr = new String( s1 ); 64 cout << *s4Ptr << "\n\n"; 68 *s4Ptr = *s4Ptr; 69 cout << *s4Ptr << '\n'; 72 delete s4Ptr; 75 s1[ 0 ] = 'H'; 76 s1[ 6 ] = 'B'; 77 cout << s1 << "\n\n"; 82 s1[ 30 ] = 'd'; // ERROR: subscript out of range 84 return 0; 86 }

55 fig08_09.cpp (1 of 3) Conversion constructor: happy Conversion constructor: birthday 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 s1 = happy birthday to you

56 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

57 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

Overloading ++ and -- Increment/decrement operators can be overloaded –Add 1 to a Date object, d1 –Prototype (member function) Date &operator++(); ++d1 same as d1.operator++() Date &Date::operator++() { helpIncrement(); return *this; } –Prototype (non-member) friend Date &operator++( Date &); ++d1 same as operator++( d1 )

Overloading ++ and -- To distinguish pre/post increment –Post increment has a dummy parameter int of 0 –Prototype (member function) Date operator++( int ); d1++ same as d1.operator++( 0 ) Date Date::operator++( int ) { Date temp = *this; helpIncrement(); return temp; } –Prototype (non-member) friend Date operator++( Data &, int ); d1++ same as operator++( d1, 0 ) –Integer parameter does not have a name Not even in function definition

Overloading ++ and -- Return values –Preincrement Returns by reference ( Date & ) lvalue (can be assigned) –Postincrement Returns by value Returns temporary object with old value rvalue (cannot be on left side of assignment) Decrement operator analogous

Case Study: A Date Class Example Date class –Overloaded increment operator Change day, month and year –Overloaded += operator –Function to test for leap years –Function to determine if day is last of month

62 date1.h (1 of 2) 1 // Fig. 8.10: date1.h …… 9 class Date { 10 friend ostream &operator<<( ostream &, const Date & ); 12 public: 13 Date( int m = 1, int d = 1, int y = 1900 ); 14 void setDate( int, int, int ); 16 Date &operator++(); 17 Date operator++( int ); 19 const Date &operator+=( int ); 21 bool leapYear( int ) const; 22 bool endOfMonth( int ) const; 24 private: 25 int month; 26 int day; 27 int year; 29 static const int days[]; 30 void helpIncrement(); 32 }; ……

63 date1.cpp (1 of 5) 1 // Fig. 8.11: date1.cpp …… 4 #include "date1.h" 8 const int Date::days[] = 9 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 12 Date::Date( int m, int d, int y ) { 14 setDate( m, d, y ); 16 } 19 void Date::setDate( int mm, int dd, int yy ) { 21 month = ( mm >= 1 && mm <= 12 ) ? mm : 1; 22 year = ( yy >= 1900 && yy <= 2100 ) ? yy : 1900; 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; 30 } 33 Date &Date::operator++() { 35 helpIncrement(); 37 return *this; 39 }

64 date1.cpp (2 of 5) 43 Date Date::operator++( int ) { 45 Date temp = *this; 46 helpIncrement(); 49 return temp; 51 } 54 const Date &Date::operator+=( int additionalDays ) { 56 for ( int i = 0; i < additionalDays; i++ ) 57 helpIncrement(); 59 return *this; 61 } 65 bool Date::leapYear( int testYear ) const { 67 if ( testYear % 400 == 0 || 68 ( testYear % 100 != 0 && testYear % 4 == 0 ) ) 69 return true; 70 else 71 return false; 73 } 54 const Date &Date::operator+=( int additionalDays ) { 56 for ( int i = 0; i < additionalDays; i++ ) 57 helpIncrement(); 59 return *this; 61 }

65 date1.cpp (4 of 5) 76 bool Date::endOfMonth( int testDay ) const { 78 if ( month == 2 && leapYear( year ) ) 79 return testDay == 29; 80 else 81 return testDay == days[ month ]; 83 } 86 void Date::helpIncrement() { 89 if ( !endOfMonth( day ) ) 90 ++day; 92 else 95 if ( month < 12 ) { 96 ++month; 97 day = 1; 98 } 101 else { year; 103 month = 1; 104 day = 1; 105 } 107 }

66 date1.cpp (5 of 5) 110 ostream &operator<<( ostream &output, const Date &d ) { 112 static char *monthName[ 13 ] = { "", "January", 113 "February", "March", "April", "May", "June", 114 "July", "August", "September", "October", 115 "November", "December" }; output << monthName[ d.month ] << ' ' 118 << d.day << ", " << d.year; 120 return output; 122 }

67 fig08_12.cpp (1 of 2) 1 // Fig. 8.12: fig08_12.cpp …… 8 #include "date1.h" 10 int main() { 12 Date d1; 13 Date d2( 12, 27, 1992 ); 14 Date d3( 0, 99, 8045 ); 16 cout << d1 << d2 << d3; 19 cout << ( d2 += 7 ); 21 d3.setDate( 2, 28, 1992 ); 22 cout << d3; 23 cout << ++d3; 25 Date d4( 7, 13, 2002 ); 27 cout << d4 << '\n'; 29 cout << ++d4 << '\n'; 30 cout << d4; 32 cout << d4 << '\n'; 34 cout << d4++ << '\n'; 35 cout << d4 << endl; 37 return 0; 39 }

68 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, d3 is February 29, 1992 Testing the preincrement operator: d4 is July 13, 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