1 overloading functions overloading operator overloading
DESCRIPTION
3 Function Overloading Overloaded functions have Same name Different sets of parameters Compiler selects proper function to execute based on number, types and order of arguments in the function call Commonly used to create several functions of the same name that perform similar tasks, but on different data types and numbers of parametersTRANSCRIPT
1
Overloading
Functions overloading Operator overloading
2
Function overloading
3
Function Overloading Overloaded functions have
• Same name• Different sets of parameters
Compiler selects proper function to execute based on number, types and order of arguments in the function call
Commonly used to create several functions of the same name that perform similar tasks, but on different data types and numbers of parameters
4
overload.cpp (1/2)
Defining a square function for ints and doubles
// function square for int valuesint square(int x){ cout << "square of integer " << x << " is "; return x * x; } // end function square with int argument
// function square for double valuesdouble square(double y) { cout << "square of double " << y << " is "; return y * y; } // end function square with double argument
5
overload.cpp (2/2)
Sample Output
Output confirms that the proper function was called in each case
int main(){ cout << square( 7 ); // calls int version cout << endl; cout << square( 7.5 ); // calls double version cout << endl; return 0; // indicates successful termination} // end main
square of integer 7 is 49square of double 7.5 is 56.25
6
More examples ...
#include <stdio.h>
int max(int a, int b) { if (a > b) return a; return b;}
char* max(char* a, char* b) { if (strcmp(a, b) > 0) return a; return b;}
int main() { cout << “max(19, 69) = “ << max(19, 69) << endl; cout << “max(“abc”, “def”) = “ << max(“abc”, “def”) << endl;
}
7
Function Overloading How the compiler differentiates overloaded functions:
• Overloaded functions are distinguished by their signaturesCompiler encodes each function identifier with the number and types of
its parameters to enable type-safe linkage • Type-safe linkage ensures that
Proper overloaded function is called Types of the arguments conform to types of the parameters
Creating overloaded functions with identical parameter lists and different return types is a compilation error• It is ambiguous on which function to call
8
Operator overloading: part I (good for users, hard for developpers )
9
MotivationClass Rational {public:
Rational(int, int) const;…Rational add(const Rational&) {…return (Rational(…));};…
private:int numerator;int denumerator;
}Rational add(const Rational& c1, const Rational& c2) {
…return Rational(…,…);
}
main() {Rational a,b,c;c=a.add(b); // member functionc=add(a,b); // non-member (global) function…
}
Ideally c = a + b;
Or Rational add(Rational) {…};
10
Operator Overloading: a syntax sugar!
‘+’ is a function (operator function),is called ‘operator+’,
and can be overloaded!
‘a+b’ is ‘operator+(a,b)’ or ‘a.operator+(b)’
a (global) non-member function
a member function
2+3 is
operator+(2,3)
11
‘addition operator’ of two Rational numbers
obj1.add(obj2) obj1 + obj2
The form of a+b is translated into a.operator+(b)
Class Rational {public:…
Rational operator+(const Rational&) {…return Rational(…);
};…
}
main() {Rational a,b,c;c=a+b;…
}
12
But,
‘a+b+c’ is fine: a.operator+(b.operator+(c)) ‘a+10’ is fine (if we modify it ): a.operator+(10)
Rational operator+(const int i) { …} How about ‘10+a’ ? 10.operator+(a)?
13
Use a non-member functionClass Rational {public:
…int numerator();int denumerator();…Rational operator+(const Rational&);Rational operator+(const int);…
}Rational operator+(const int num1, const Rational& r2) {
…return Rational(numerator(…),denumerator(…));
}
main() {Rational a,b,c;c=10+a;c=a+10;…
} A call of a+b is then converted to operator+
(a,b) 10+a operator+(10,a) (a normal function
call, not a ‘method’ of an object)
If the first operand (or the left operand) is not an object of the same class, we cannot use a ‘member function’, so have to use a normal overloaded function.
14
‘Friend’ is coming to help … We can define (global) functions or classes to be friends
of a class to allow them direct access to its private data members
Class Rational { ... public: ... friend Rational operator+(const Rational&, const Rational&); };
Rational operator+(const Rational& op1, const Rational& op2) { int numerator = op1.numerator*op2.denumerator + op2.numerator*op1.denumerator;
int denumerator = op1.denumerator*op2.denumerator; return(Rational(numerator,denumberator)); }
Access to private data thanks to the ‘friendship’!
No ‘friend’, we need to do: op1.numerator();
15
Overloading the assignment operator =
16
Assignment Operator ‘=‘
Assignment operator (=) can be used to assign an object to another object of the same type• Member-wise assignment: each data member of the right object is
assigned to the same data member in the left object
A a,b;a = b;
17
class T { ... public: ... void operator=(const T&);
...};
void T::operator=(const T& right) {…
}
main() {
T a,b; …a = b; // a.operator=(b)…
}
OK for a = b, But not for the chaining of assignments: a = b = c = …
a.operator=(b.operator=(c))
it can NOT be a const function, as ‘=‘ modifies the object
It should be an object here …
18
X f() { X x; return x;}
‘return x’ returns a temporay object ‘temp’ of class X by constructor (because x is a local object, and to be lost!)
A function returning an object
19
const X f() { X x; return x;}
It’s the same, but enforces that it cannot be a left value
A function returning a constant object ?
20
Class Rational {public:
…
…const Rational operator+(const Rational& r2) const;const Rational operator+(const int num2) const;…
}
main() {Rational a,b,c;c=a+10;…
}
Put ‘const’ everywhere, three different places
21
class X {public: X() {cout << "constructor\n";} X(const X& x){cout << "copy constructor\n"; }};
// return an object of XX f() { X x; return x;}
// must be rvalueconst X cf() { X x; return x;}
constructor (for X x in main)constructor (for X y in main)
constructor (for X x in f)copy constructor (Unix has that, but not Linux, for return x in f)
constructor (for X x in cf)copy constructor (Unix has that, but not Linux, for return x in cf)
int main() { X x,y;
f() = x; // No compilation error but does nothing
f = cf(); // cfx() = x is error }
Excercises:
22
X f(X x) { X a; return a;}
A constructor is called when: declare/define objects pass by value return by value
23
X& f() {
…
}
A function returning a reference ?
24
Object references
class A {public:
getx();private:
int x;}
ap->getx();(*ap).getx();
delete ap;
A a;A& b=a;
Access and deletion
We have pointers to class objects (low-level manipulations)
int i;int& j = i;
We also have references to objects
25
class A {public:
A& f(A a);private:
int x;}
A& A::f(A a) {A b;…return b;
}A& A::f(A a) {
…return a;
}A& A::f(A& a) {
A b;…return a;
}
returning a reference
class A {public:
A f(A a);private:
int x;}
A A::f(A a) {A b;…return b;
}
main() {A a,b,c;c = a.f(b);}
A function returning an object
but the referenced object should exisit!
No! b disappears
No! a disappears
OK!
26
class A {public:
A& f(A a);private:
int x;}
const A& A::f(const A& a) {…return a;
}
‘return by value’ is safe. Avoid ‘return by reference’.If we want to avoid the copy, we ‘return by constant reference’!
‘return by constant reference’ means that the object being returned cannot itself be modified later on!
‘references’ to local variables are not possible! The object have to exist after the function!
27
class X {public: X() {cout << "constructor\n";} X(const X& x){cout << "copy constructor\n"; }};
// return an object of XX f() { X x; return x;}
// must be rvalueconst X cf() { X x; return x;}
// must be rvalueconst X& crf(X& x){ return x;}
//can be rvalue or lvalueX& rf(X& x){ return x; }
constructor (for X x in main)constructor (for X y in main)
constructor (for X x in f)copy constructor (Unix has that, but not Linux, for return x in f)
constructor (for X x in cf)copy constructor (Unix has that, but not Linux, for return x in cf)
int main() { X x,y;
f() = x; // No compilation error but does nothing
f = cf(); // cfx() = x is error f = rf( y );
f = crf( y ); // crfx( y ) = x is error return 0;}
28
Object self-reference: the ‘this’ pointer
Function members
Data members
Class Object
this
*this
Every class has a keyword, ‘this’, which is a pointer to the object itself. Thus, *this is the object itself!
A& F::f(){ // … return *this;}
Can return the modified object.int i;int& j = i;
29
Returning a reference or a const reference?
a = b = c always means a = (b = c) as ‘=‘ is right associative, it is a r-value.
r-value, appear on the right side of assignment, ‘readable’l-value, on the left side, ‘writable’
We can write (a=b)=c, depending on what a=b returns.
int i=5, j=4;
(i=j)=3; // lvalue, return the new i cout << i<< j ; // get 3 4
(i=3)=4; // lvalue, return the new i cout << i<< j ; // get 4 4
i = j = 3; // get 3 3
30
We cannot write (a = b) = c if we return a const ref:const T& operator=(const T&);
We can do (a=b)=c if we return a non-constant ref: T& operator=(const T&);
It can be both a l-value and r-value!
31
class T { ... public: ... T& operator=(const T&);
...};
T& T::operator=(const T& right) {…return *this;
}
main() {
T a,b; …b = a; // b.operator=(a)…
}
*this refers to the calling object
Returning a reference allows the chaining of operatorsa = b = c = d; a = (b = (c = d)) a.operator=(b.operator=(c.operator=(d)))
it can NOT be a const function, as ‘=‘ modifies the object
32
class T { ... public: ... T& operator=(const T& right);
...};
T& T::operator=(const T& right) {if (this == &right) return *this;…return *this;
}
main() {
T a,b; …b = a; // b.operator=(a)…
}
1. Const reference for the argument (a r-value)
2. Return a reference to the left-hand side (a l-value), and *this is converted into a reference
3. Check for self-assignment
Summary on ‘=‘ overloading
33
Other operators such as+=,-=,*=, …can be overloaded in a similar manner.
34
Overloading input/output streams
35
Input/outputclass T { ...};
ostream& operator<<(ostream& out, const T t) {…return out;
}
istream& operator>>(istream& in, T& t) {…return in;
}
main() {
T a;…cin >> a;cout << a;…
} Before, we wrote a ‘display’ or ‘print’ function.
‘Rational’ examplevoid Rational::Display() const {
cout << Numerator << '/' << Denominator;}
Examplet.Display();
ostream& operator<<(ostream& out, const Rational t) { out << Numerator << '/' << Denominator;return out;
}
Example cout << t;
ofstream fout(“toto”); fout.open(…); fcout << t;
void Rational::Get() {char slash;cin >> Numerator >> slash >> Denominator;if(Denominator == 0){ cout << "Illegal denominator of zero, "
<< "using 1 instead" << endl; Denominator = 1;}
}
Examplet.Get();
istream& operator>>(istream& in, T& t) {char slash;in >> Numerator >> slash >> Denominator;if(Denominator == 0){
cout << "Illegal denominator of zero, " << "using 1 instead" << endl;
Denominator = 1;}
return in;}
Examplecin >> t;
38
Which operators to overload? Only those for which it makes sense … … and for which there is a genuine need … … and which the users will expect Typically these are usually appropriate:
= << >>
If the class involves ‘arithmetic type’ (e.g. complex, rational, vector, matrix, …), arithmetic operations should be provided.
39
Essential operators
class X {X();X(const X&);~X();X& operator=(const X&);
…}
ostream& operator<<(ostream& out, const X x) {…
}
40
How to ‘hide’ or ‘disable’ an operator?
class X {private:
void operator=(const X&);void operator&();void operator,(const X&);…
}
Void f(X a, X b) {a=b; // error: operator= private&a; // error: operator& privatea,b; // error: operator, private
}
41
Use a private function to overload others
class Rational {public:
const Rational operator+(Rational r) {return add(…);};const Rational operator+(int i) {return add(…);};const Rational operator+(…) {return add(…);}
private:const Rational add(a,b,c,d) {return Rational(a*d+b*c,b*d);}
}
const Rational operator+(int i, Rational) {return add(…);
} This also gives one example of defin ring a ‘private’ member function.
42
Operator overloading: part II
43
Restrictions on Operator Overloading Cannot change
• Precedence of operator (order of evaluation)Use parentheses to force order of operators
• Associativity (left-to-right or right-to-left)2*3*4 (=6*4) vs. 2^3^2 (=2^9)
• Number of operandse.g., !, & or * is unary, i.e., can only act on one operand as in &i or *ptr
• How operators act on built-in/primitive data types (i.e., cannot change integer addition)
Cannot create new operators Operators must be overloaded explicitly
• Overloading + and = does not overload +=
44
Operators that can be overloaded+ - * / % ^ & |~ ! = < > += -= *=/= %= ^= &= |= << >> >>=
<<= == != <= >= && || ++-- ->* , -> [] () new delete
new[] delete[]
Operators that cannot be overloaded
. .* ? :
Member functions declaration: bool operator!() const; bool operator==(const T&) const; bool operator<(const T&) const; bool operator!=(const T& right) const; bool operator>( const T& right) const; bool operator<=(const T& right) const; bool operator>=(const T& right) const;
45
Operators as Class Members
Leftmost object must be of the same class as operator function
Use this keyword to explicitly get left operand argument Operators (), [], -> or some other assignment operator
must be overloaded as a class member function Called when
• Left operand of binary operator is of this class• Single operand of unary operator is of this class
46
Operators as Global Functions
Need parameters for both operands Can have object of different class Can be a friend to access private (or protected) data Both << and >> must be global functions
• Cannot be class members Overloaded << operator
• Left operand is of type ostream&Such as cout object in cout << classObject
Similarly, overloaded >> has left operand of istream&• Such as cin object in cin >> classObject
47
Commutative Operators for global functions
May want + to be commutative• So both “a + b” and “b + a” work
Suppose we have two different classes• If the overloaded operator is a member function, then its class is on left
HugeIntClass + long int• Can be member function for HugeIntClass
HugeIntClass + HugeIntClass• Can be member function as well
long int + HugeIntClass• For this to work, + needs to be a global overloaded function
HugeInt operator+( long, HugeInt ); // function overloading HugeInt operator+( HugeInt, long ); HugeInt operator+( HugeInt, HugeInt );
48
Overloading Unary Operators Can overload as member function with no arguments Can overload as global function with one argument
• Argument must be class object or reference to class object If member function, needs no arguments• bool operator!() const;
If global function, needs one argument• bool operator!( const T& ), i.e., !f becomes operator!(f)
49
Overloading Binary Operators Member function: one argument• const T& operator+=(const T&);• s1 += s2; // a string• s1 += s2 += s3; // same as s1 += ( s2 += s3 );• (s1 += s2) += s3; // compiler yells
Global function: two arguments• One of the arguments must be class object or reference• const T& operator+=(T&, const T&); // no const for the first argument• y += z becomes operator+=( y, z )
Note that int type provides a variant of lvalue:
int i=2,j=4;(j +=i) += 2; // return the new jcout << i << j; // output 2 8
50
Overloading subscription operators
51
Subscription Operator ‘[]‘
A a,b;a[3];
For example, we can enable this operator for a list (whether it is array-based or linked):
List l;L[10]
Or we can re-number from 1 instead of 0 …
52
T& operator[](int);
It returns the object at the given integer index It can be both lvalue and rvalue
T& operator[](int i){ …};
53
// subscript operator: if you only want it to be an rvalue T operator[](int) const; // constant member function; cannot be lvalue // May also be
// const T& operator[](int) const; // but NOT
// T& operator[](int) const; // (compile error)
The ‘const’ matters, and is part of the prototype,• We call it const overloading (the prototypes above)
The compiler decides based on the type of the calling object. • If it is const object, the const member function will be used.
Sometimes we need this if we want to use a different member function for a const object.
• If it is not a const object, the non-const function will be used, no matter whether it is a rvalue or lvalue
54
#include <iostream>using namespace std;
class B {public: const int& operator[](int i) const{ cout << "Constant [] function is called" << endl; return data[i]; } int& operator[](int i){ cout << "Non-constant [] function is called" << endl; return data[i]; }private: int data[10];};
int main(){ B b1; const B bc = b1; b1[0]; b1[2] = bc[2]; cout << bc[1] << endl; return 0;}
Non-constant [] function is called (for b1[0])Non-constant [] function is called (for b1[2])Constant [] function is called (for bc[2])Constant [] function is called (for bc[1])0
55
T operator()(int, int = 0) const; // at most 2 parameters
A a,b;a(3);
A a,b;a(3,1);
56
Case Study: String Class
Build class String• String creation, manipulation• Similar to class string in standard library
Conversion constructor• Any single-argument constructor• Turns objects of other types into class objects• Example: String s1( "happy" );
Creates a String from a char *
Overloading function call operator String.h, String.cpp, stringtester.cpp
57
class String {friend ostream &operator<<( ostream &, const String & ); // global I/O functions friend istream &operator>>( istream &, String & ); public:
String( const char * = "" ); // conversion/default constructor String( const String & ); // copy constructor ~String(); // destructor
const String &operator=( const String & ); // assignment operator: s1 = s2 = s3; const String &operator+=( const String & ); // concatenation operator: s1 += s2 += s3;
bool operator!() const; // is String empty? bool operator==( const String & ) const; // test s1 == s2 bool operator<( const String & ) const; // test s1 < s2
// test s1 != s2 bool operator!=( const String &right ) const { return !( *this == right ); } // end function operator!=
// test s1 > s2 bool operator>( const String &right ) const { return right < *this; // use the implemented < operator } // end function operator>
// test s1 <= s2 bool operator<=( const String &right ) const { return !( right < *this ); // use the implemented < operator } // end function operator <=
// test s1 >= s2 bool operator>=( const String &right ) const { return !( *this < right ); // use the implemented < operator } // end function operator>=
char &operator[]( int ); // subscript operator (modifiable lvalue) char operator[]( int ) const; // subscript operator (rvalue)
// return a substring. // s(4, 5) returns the substring including and from s[4] for 5 characters // s(4) returns the right part of the string String operator()( int, int = 0 ) const;
int getLength() const; // return string length private:
int length; // string length (not counting null terminator) char *sPtr; // pointer to start of pointer-based string void setString( const char * ); // utility function
}; // end class String
58
stringtester.cpp Sample Output (1/3)
Conversion (and default) constructor: happyConversion (and default) constructor: birthdayConversion (and default) constructor:s1 is "happy"; s2 is " birthday"; s3 is ""
The results of comparing s2 and s1:s2 == s1 yields falses2 != s1 yields trues2 > s1 yields falses2 < s1 yields trues2 >= s1 yields falses2 <= s1 yields true
Testing !s3:s3 is empty; assigning s1 to s3;operator= calleds3 is "happy"
s1 += s1 += s2 yields s1 = happy birthdayhappy birthday
59
stringtester.cpp Sample Output (2/3)
s1 += " to you" yieldsConversion (and default) constructor: to youDestructor: to yous1 = happy birthdayhappy birthday to you
Conversion (and default) constructor: happy birthdayCopy constructor: happy birthdayDestructor: happy birthdayThe substring of s1 starting atlocation 0 for 14 characters, s1(0, 14), is:happy birthday
Destructor: happy birthdayConversion (and default) constructor: appy birthday to youCopy constructor: appy birthday to youDestructor: appy birthday to youThe substring of s1 starting atlocation 15, s1(15), is: appy birthday to you
The constructor and destructor are called
for the temporary String
60
stringtester.cpp Sample Output (3/3)
Destructor: appy birthday to youCopy constructor: happy birthdayhappy birthday to you
*s4Ptr = happy birthdayhappy birthday to you
Assigning *s4Ptr to *s4Ptroperator= calledAttempted assignment of a String to itself*s4Ptr = happy birthdayhappy birthday to youDestructor: happy birthdayhappy birthday to you
s1 after s1[0] = 'H' and s1[6] = 'B' is: Happy Birthdayhappy birthday to you
Attempt to assign 'd' to s1[30] yields:Destructor: happyDestructor: birthdayDestructor: Happy Birthdayhappy birthday td you
61
Overloading ++, -- operators
62
Overloading ++ and --
Increment/decrement operators can be overloaded Prefix increment: ++x Postfix increment: x++
operator++()
operator++(int)
For pointer applications!
63
Prefix increment Member-function prototype for prefix increment
• Date& operator++(); // return a reference for // successive operation: y=++++x• ++d d.operator++()
Global-function prototype for prefix increment• Date& operator++(Date&);• ++d operator++(d)
class X {public:
X& operator++() {...return *this;}
...;}
X x;++x; d++++x (x.operator++()).operator++()
64
Postfix Increments Member-function prototype for postfix increment:• T operator++(int); // must be rvalue;• d++ d1.operator++(0)
Global-function prototype for postfix increment• T operator++(T&, int); • d++ operator++(d, 0)
class X {public:
X operator++(int) {X old = *this;...return old;}
...;}X x;x++;
A dummy parameter
d++++ impossible cascating!
int i;i++++; NON!++++i; OK!
65
Case Study: A Date Class Overloaded increment operator
• Change day, month and year Function to test for leap years Function to determine if a day is last of month Date.h, Date.cpp, datetester.cpp
66
Date.hclass Date{ friend ostream& operator<<( ostream&, const Date& );public: // default constructor Date( int m = 1, int d = 1, int y = 1900 ); void setDate( int, int, int ); // set month, day, year Date& operator++(); // prefix increment operator, ++Date Date operator++( int ); // postfix increment operator, Date++ const Date& operator+=( int ); // add days, modify object bool leapYear( int ) const; // is date in a leap year? bool endOfMonth( int ) const; // is date at the end of month?private: int month; int day; int year; static const int days[]; // static member variable; array of days per month void helpIncrement(); // utility function incrementing date}; // end class Date
Note the difference between prefix and postfix increment
67
Date.cpp (1/5)#include "Date.h"
// initialize static member at file scope; one classwide copyconst int Date::days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
// Date constructorDate::Date( int m, int d, int y ) { setDate( m, d, y ); } // end Date constructor
// set month, day and yearvoid Date::setDate( int mm, int dd, int yy ) { month = ( mm >= 1 && mm <= 12 ) ? mm : 1; year = ( yy >= 1900 && yy <= 2100 ) ? yy : 1900;
// test for a leap year if ( month == 2 && leapYear( year ) ) day = ( dd >= 1 && dd <= 29 ) ? dd : 1; else day = ( dd >= 1 && dd <= days[ month ] ) ? dd : 1;} // end function setDate
68
Date.cpp (2/5)// overloaded prefix increment operator Date& Date::operator++(){ helpIncrement(); // increment date return *this; // reference return to create an lvalue} // end function operator++
// overloaded postfix increment operator; note that the // dummy integer parameter does not have a parameter nameDate Date::operator++( int ){ Date temp = *this; // hold current state of object helpIncrement();
// return unincremented, saved, temporary object return temp; // value return; not a reference return} // end function operator++
Postfix increment updates object and returns a copy of the original
Do not return a reference to temp, because returning a reference may make the variable a lvalue. Since temp is a local variable, it will be destroyed leading to access error
69
Date.cpp (3/5)// add specified number of days to dateconst Date& Date::operator+=( int additionalDays ) { for ( int i = 0; i < additionalDays; i++ ) helpIncrement(); return *this; // enables cascading} // end function operator+=
// if the year is a leap year, return true; otherwise, return falsebool Date::leapYear( int testYear ) const { if ( testYear % 400 == 0 || (testYear % 100 != 0 && testYear % 4 == 0) ) return true; // a leap year else return false; // not a leap year} // end function leapYear
// determine whether the day is the last day of the monthbool Date::endOfMonth( int testDay ) const { if ( month == 2 && leapYear( year ) ) return testDay == 29; // last day of Feb. in leap year else return testDay == days[ month ];} // end function endOfMonth
70
Date.cpp (4/5)// function to help increment the datevoid Date::helpIncrement(){ // day is not end of month if ( !endOfMonth( day ) ) day++; // increment day else if ( month < 12 ) // day is end of month and month < 12 { month++; // increment month day = 1; // first day of new month } // end if else // last day of year { year++; // increment year month = 1; // first month of new year day = 1; // first day of new month } // end else} // end function helpIncrement
71
Date.cpp (5/5)// overloaded output operatorostream& operator<<( ostream& output, const Date& d ){ static char* monthName[ 13 ] = { "", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; output << monthName[ d.month ] << ' ' << d.day << ", " << d.year; return output; // enables cascading} // end function operator<<
72
datetester.cppDate d1; // defaults to January 1, 1900Date d2( 12, 27, 1992 ); // December 27, 1992Date d3( 0, 99, 8045 ); // invalid date
cout << "d1 is " << d1 << "\nd2 is " << d2 << "\nd3 is " << d3;cout << "\n\nd2 += 7 is " << ( d2 += 7 );
d3.setDate( 2, 28, 1992 );cout << "\n\n d3 is " << d3;cout << "\n++d3 is " << ++d3 << " (leap year allows 29th)";
Date d4( 7, 13, 2002 );cout << "\n\nTesting the prefix increment operator:\n“ << " d4 is " << d4 << endl;cout << "++d4 is " << ++d4 << endl;cout << " d4 is " << d4;cout << "\n\nTesting the postfix increment operator:\n“ << " d4 is " << d4 << endl;cout << "d4++ is " << d4++ << endl;cout << " d4 is " << d4 << endl;
Demonstrate prefix increment
Demonstrate postfix increment
73
datetester.cpp Sample Outputd1 is January 1, 1900d2 is December 27, 1992d3 is January 1, 1900 d2 += 7 is January 3, 1993 d3 is February 28, 1992++d3 is February 29, 1992 (leap year allows 29th) Testing the prefix increment operator: d4 is July 13, 2002++d4 is July 14, 2002 d4 is July 14, 2002 Testing the postfix increment operator: d4 is July 14, 2002d4++ is July 14, 2002 d4 is July 15, 2002