Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 Overloading  Functions overloading  Operator overloading.

Similar presentations


Presentation on theme: "1 Overloading  Functions overloading  Operator overloading."— Presentation transcript:

1 1 Overloading  Functions overloading  Operator overloading

2 2 Function overloading

3 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 4 overload.cpp (1/2)  Defining a square function for ints and doubles // function square for int values int square(int x) { cout << "square of integer " << x << " is "; return x * x; } // end function square with int argument // function square for double values double square(double y) { cout << "square of double " << y << " is "; return y * y; } // end function square with double argument

5 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 49 square of double 7.5 is 56.25

6 6 More examples... #include 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 7 Function Overloading  How the compiler differentiates overloaded functions: Overloaded functions are distinguished by their signatures  Compiler 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 8 Operator overloading: part I (good for users, hard for developpers )

9 9 Motivation Class 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 function c=add(a,b);// non-member (global) function … } Ideally  c = a + b; Or Rational add(Rational) {…};

10 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 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 12 But, l ‘a+b+c’ is fine: a.operator+(b.operator+(c)) l ‘a+10’ is fine (if we modify it ): a.operator+(10) Rational operator+(const int i) { …} l How about ‘10+a’ ? 10.operator+(a)?

13 13 Use a non-member function Class 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 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 15 Overloading the assignment operator =

16 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 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 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 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 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 21 class X { public: X() {cout << "constructor\n";} X(const X& x){cout << "copy constructor\n"; } }; // return an object of X X f() { X x; return x; } // must be rvalue const 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 22 X f(X x) { X a; return a; } A constructor is called when: l declare/define objects l pass by value l return by value

23 23 X& f() { … } A function returning a reference ?

24 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 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 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 27 class X { public: X() {cout << "constructor\n";} X(const X& x){cout << "copy constructor\n"; } }; // return an object of X X f() { X x; return x; } // must be rvalue const X cf() { X x; return x; } // must be rvalue const X& crf(X& x){ return x; } //can be rvalue or lvalue X& 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 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 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 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 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 operators a = 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 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 33 Other operators such as +=, -=, *=, … can be overloaded in a similar manner.

34 34 Overloading input/output streams

35 35 Input/output class 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.

36 ‘Rational’ example void Rational::Display() const { cout << Numerator << '/' << Denominator; } Example t.Display(); ostream& operator<<(ostream& out, const Rational t) { out << Numerator << '/' << Denominator; return out; } Example cout << t; ofstream fout(“toto”); fout.open(…); fcout << t;

37 void Rational::Get() { char slash; cin >> Numerator >> slash >> Denominator; if(Denominator == 0){ cout << "Illegal denominator of zero, " << "using 1 instead" << endl; Denominator = 1; } Example t.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; } Example cin >> t;

38 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 39 Essential operators class X { X(); X(const X&); ~X(); X& operator=(const X&); … } ostream& operator<<(ostream& out, const X x) { … }

40 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& private a,b;// error: operator, private }

41 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 42 Operator overloading: part II

43 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 operands  e.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 44 Operators that can be overloaded +-*/%^&| ~!=<>+=-=*= /=%=^=&=|=<<>>>>= <<===!=<=>=&&||++ --->*,->[]()newdelete 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 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 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 > 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 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 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 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 j cout << i << j; // output 2 8

50 50 Overloading subscription operators

51 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 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 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 54 #include 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 55 T operator()(int, int = 0) const; // at most 2 parameters A a,b; a(3); A a,b; a(3,1);

56 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 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 // 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 = 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 58 stringtester.cpp Sample Output (1/3) Conversion (and default) constructor: happy Conversion (and default) constructor: birthday Conversion (and default) 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 += s1 += s2 yields s1 = happy birthdayhappy birthday

59 59 stringtester.cpp Sample Output (2/3) s1 += " to you" yields Conversion (and default) constructor: to you Destructor: to you s1 = happy birthdayhappy birthday to you Conversion (and default) 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 (and default) constructor: appy birthday to you Copy constructor: appy birthday to you Destructor: appy birthday to you The substring of s1 starting at location 15, s1(15), is: appy birthday to you The constructor and destructor are called for the temporary String

60 60 stringtester.cpp Sample Output (3/3) Destructor: appy birthday to you Copy constructor: happy birthdayhappy birthday to you *s4Ptr = happy birthdayhappy birthday to you Assigning *s4Ptr to *s4Ptr operator= called Attempted assignment of a String to itself *s4Ptr = happy birthdayhappy birthday to you Destructor: 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: happy Destructor: birthday Destructor: Happy Birthdayhappy birthday td you

61 61 Overloading ++, -- operators

62 62 Overloading ++ and --  Increment/decrement operators can be overloaded  Prefix increment: ++x  Postfix increment: x++ operator++() operator++(int) For pointer applications!

63 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 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 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 66 Date.h class 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 67 Date.cpp (1/5) #include "Date.h" // initialize static member at file scope; one classwide copy const int Date::days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; // Date constructor Date::Date( int m, int d, int y ) { setDate( m, d, y ); } // end Date constructor // set month, day and year void 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 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 name Date 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 69 Date.cpp (3/5) // add specified number of days to date const 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 false bool 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 month bool 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 70 Date.cpp (4/5) // function to help increment the date void 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 71 Date.cpp (5/5) // overloaded output operator ostream& 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 72 datetester.cpp Date d1; // defaults to January 1, 1900 Date d2( 12, 27, 1992 ); // December 27, 1992 Date 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 73 datetester.cpp Sample Output 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 (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, 2002 d4++ is July 14, 2002 d4 is July 15, 2002


Download ppt "1 Overloading  Functions overloading  Operator overloading."

Similar presentations


Ads by Google