Title: Overloading
1- Functions overloading
- Operator overloading
2Function overloading
3Function 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
4overload.cpp (1/2)
- Defining a square function for ints and doubles
// function square for int values int square(int
x) cout ltlt "square of integer " ltlt x ltlt "
is " return x x // end function square
with int argument // function square for double
values double square(double y) cout ltlt
"square of double " ltlt y ltlt " is " return y
y // end function square with double argument
5overload.cpp (2/2)
- Sample Output
- Output confirms that the proper function was
called in each case
int main() cout ltlt square( 7 ) // calls int
version cout ltlt endl cout ltlt square( 7.5
) // calls double version cout ltlt endl
return 0 // indicates successful termination
// end main
square of integer 7 is 49 square of double 7.5 is
56.25
6More examples ...
- include ltstdio.hgt
- int max(int a, int b)
- if (a gt b) return a
- return b
-
- char max(char a, char b)
- if (strcmp(a, b) gt 0) return a
- return b
-
- int main()
- cout ltlt max(19, 69) ltlt max(19, 69) ltlt
endl - cout ltlt max(abc, def) ltlt max(abc,
def) ltlt endl -
7Function 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
8Operator overloading part I (good for users,
hard for developpers )
9Motivation
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 ca.add(b) // member function cadd(a,b
) // non-member (global) function
Or Rational add(Rational)
Ideally ? c a b
10Operator Overloading a syntax sugar!
is a function (operator function), is called
operator, and can be overloaded!
23 is operator(2,3)
ab is operator(a,b) or a.operator(b)
a member function
a (global) non-member function
11addition operator of two Rational numbers
obj1.add(obj2) ? obj1 obj2
Class Rational public Rational
operator(const Rational) return
Rational() main() Rational
a,b,c cab
The form of ab is translated into a.operator(b)
12But,
- abc is fine a.operator(b.operator(c))
- a10 is fine (if we modify it )
a.operator(10) - Rational operator(const int i)
- How about 10a ? 10.operator(a)?
13Use a non-member function
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.
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 c10a ca10
- A call of ab is then converted to operator(a,b)
- 10a ? operator(10,a) (a normal function call,
not a method of an object)
14Friend 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.numeratorop2.denumerator
op2.numeratorop1.denumerator - int denumerator op1.denumeratorop2.denumerato
r - return(Rational(numerator,denumberator))
-
Access to private data thanks to the friendship!
No friend, we need to do op1.numerator()
15Overloading the assignment operator
16Assignment Operator
A a,b a b
- 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
17- class T
- ...
- public
- ...
- void operator(const T)
- ...
-
- void Toperator(const T right)
-
-
-
- main()
- T a,b
-
- a b // a.operator(b)
it can NOT be a const function, as modifies
the object
OK for a b, But not for the chaining of
assignments a b c a.operator(b.operator
(c))
It should be an object here
18A function returning an object
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!)
19A function returning a constant object ?
const X f() X x return x
Its the same, but enforces that it cannot be a
left value
20Put const everywhere, three different places
Class Rational public const Rational
operator(const Rational r2) const const
Rational operator(const int num2)
const main() Rational
a,b,c ca10
21Excercises
class X public X() cout ltlt
"constructor\n" X(const X x)cout ltlt "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
22- A constructor is called when
- declare/define objects
- pass by value
- return by value
X f(X x) X a return a
23A function returning a reference ?
X f()
24Object references
We have pointers to class objects (low-level
manipulations)
ap-gtgetx() (ap).getx() delete ap
class A public getx() private int x
Access and deletion
We also have references to objects
int i int j i
A a A ba
25A function returning an object
returning a reference
class A public A f(A a) private int
x A Af(A a) A b return b main()
A a,b,c c a.f(b)
class A public A f(A a) private int
x A Af(A a) A b return b A
Af(A a) return a A Af(A a) A
b return a
No! b disappears
No! a disappears
OK!
but the referenced object should exisit!
26class A public A f(A a) private int
x const A Af(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!
references to local variables are not possible!
The object have to exist after the function!
return by constant reference means that the
object being returned cannot itself be modified
later on!
27class X public X() cout ltlt
"constructor\n" X(const X x)cout ltlt "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
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
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)
28Object self-reference the this pointer
Every class has a keyword, this, which is a
pointer to the object itself. Thus, this is the
object itself!
Class Object
Function members
A Ff() // return this
this
Data members
this
Can return the modified object.
int i int j i
29Returning 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 (ab)c, depending on
what ab returns.
int i5, j4 (ij)3 // lvalue,
return the new i cout ltlt iltlt j // get 3 4
(i3)4 // lvalue, return the new i
cout ltlt iltlt 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 (ab)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 Toperator(const T right)
-
- return this
-
- main()
- T a,b
-
- b a // b.operator(a)
it can NOT be a const function, as modifies
the object
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)))
32Summary on overloading
- class T
- ...
- public
- ...
- T operator(const T right)
- ...
-
- T Toperator(const T right)
- if (this right) return this
-
- return this
-
- main()
- T a,b
-
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
33Other operators such as , -, , can be
overloaded in a similar manner.
34Overloading input/output streams
35Input/output
- class T
- ...
-
- ostream operatorltlt(ostream out, const T t)
-
- return out
-
- istream operatorgtgt(istream in, T t)
-
- return in
-
- main()
- T a
-
Before, we wrote a display or print function.
36Rational example
- void RationalDisplay() const
- cout ltlt Numerator ltlt '/' ltlt Denominator
-
- Example
- t.Display()
ostream operatorltlt(ostream out, const Rational
t) out ltlt Numerator ltlt '/' ltlt
Denominator return out Example cout ltlt
t ofstream fout(toto) fout.open()
fcout ltlt t
37- void RationalGet()
- char slash
- cin gtgt Numerator gtgt slash gtgt Denominator
- if(Denominator 0)
- cout ltlt "Illegal denominator of zero, "
- ltlt "using 1 instead" ltlt endl
- Denominator 1
-
-
- Example
- t.Get()
istream operatorgtgt(istream in, T t) char
slash in gtgt Numerator gtgt slash gtgt
Denominator if(Denominator 0) cout ltlt
"Illegal denominator of zero, " ltlt "using
1 instead" ltlt endl Denominator
1 return in Example cin gtgt t
38Which 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
-
- ltlt
- gtgt
- If the class involves arithmetic type (e.g.
complex, rational, vector, matrix, ), arithmetic
operations should be provided.
39Essential operators
class X X() X(const X) X() X
operator(const X) ostream
operatorltlt(ostream out, const X x)
40How 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) ab // error
operator private a // error operator
private a,b // error operator, private
41Use 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 cons
t Rational add(a,b,c,d) return
Rational(adbc,bd) 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
43Restrictions 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)
- 234 (64) vs. 232 (29)
- 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 Operators that can be overloaded Operators that can be overloaded Operators that can be overloaded Operators that can be overloaded Operators that can be overloaded Operators that can be overloaded Operators that can be overloaded Operators that can be overloaded
- /
! lt gt -
/ ltlt gtgt gtgt
ltlt ! lt gt
-- -gt , -gt () new delete
new delete
Operators that cannot be overloaded Operators that cannot be overloaded Operators that cannot be overloaded Operators that cannot be overloaded Operators that cannot be overloaded Operators that cannot be overloaded Operators that cannot be overloaded Operators that cannot be overloaded
. . ?
Member functions declaration bool
operator!() const bool operator(const T)
const bool operatorlt(const T) const
bool operator!(const T right) const bool
operatorgt( const T right) const bool
operatorlt(const T right) const bool
operatorgt(const T right) const
45Operators as Class Members
- Leftmost object must be of the same class as
operator function - Use this keyword to explicitly get left operand
argument - Operators (), , -gt 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
46Operators 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 ltlt and gtgt must be global functions
- Cannot be class members
- Overloaded ltlt operator
- Left operand is of type ostream
- Such as cout object in cout ltlt classObject
- Similarly, overloaded gtgt has left operand of
istream - Such as cin object in cin gtgt classObject
47Commutative 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 )
48Overloading 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)
49Overloading 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 i2,j4 (j i) 2 // return the new
j cout ltlt i ltlt j // output 2 8
50Overloading subscription operators
51Subscription Operator
A a,b a3
For example, we can enable this operator for a
list (whether it is array-based or linked) List
l L10 Or we can re-number from 1 instead of 0
52T 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
54include ltiostreamgt using namespace std class B
public const int operator(int i) const
cout ltlt "Constant function is called" ltlt
endl return datai int
operator(int i) cout ltlt "Non-constant
function is called" ltlt endl return datai
private int data10 int main() B
b1 const B bc b1 b10 b12
bc2 cout ltlt bc1 ltlt endl return 0
Non-constant function is called (for
b10) Non-constant function is called (for
b12) Constant function is called (for
bc2) Constant function is called (for
bc1) 0
55A a,b a(3)
A a,b a(3,1)
T operator()(int, int 0) const // at
most 2 parameters
56Case 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
57class String friend ostream operatorltlt(
ostream , const String ) // global I/O
functions friend istream operatorgtgt( 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 operatorlt( const
String ) const // test s1 lt s2 // test s1
! s2 bool operator!( const String right )
const return !( this right ) // end
function operator! // test s1 gt s2 bool
operatorgt( const String right ) const
return right lt this // use the implemented lt
operator // end function operatorgt // test
s1 lt s2 bool operatorlt( const String right )
const return !( right lt this ) // use the
implemented lt operator // end function operator
lt // test s1 gt s2 bool operatorgt( const
String right ) const return !( this lt
right ) // use the implemented lt operator //
end function operatorgt 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
s4 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
58stringtester.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 gt s1 yields
false s2 lt s1 yields true s2 gt s1 yields
false s2 lt 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
59stringtester.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
60stringtester.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 s10 'H' and s16 'B' is
Happy Birthdayhappy birthday to you Attempt to
assign 'd' to s130 yields Destructor
happy Destructor birthday Destructor Happy
Birthdayhappy birthday td you
61Overloading , -- operators
62Overloading and --
- Increment/decrement operators can be overloaded
- Prefix increment x
- Postfix increment x
operator()
operator(int)
For pointer applications!
63Prefix increment
- Member-function prototype for prefix increment
- Date operator() // return a reference for
- // successive operation
yx - 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
dx ? (x.operator()).operator()
64Postfix 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)
A dummy parameter
class X public X operator(int) X old
this ... return old ... X x x
int i i NON! i OK!
d ? impossible cascating!
65Case 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
66Date.h
class Date friend ostream operatorltlt(
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
67Date.cpp (1/5)
include "Date.h" // initialize static member at
file scope one classwide copy const int
Datedays 0, 31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31 // Date
constructor DateDate( int m, int d, int y )
setDate( m, d, y ) // end Date
constructor // set month, day and year void
DatesetDate( int mm, int dd, int yy )
month ( mm gt 1 mm lt 12 ) ? mm 1 year
( yy gt 1900 yy lt 2100 ) ? yy 1900
// test for a leap year if ( month 2
leapYear( year ) ) day ( dd gt 1 dd lt
29 ) ? dd 1 else day ( dd gt 1
dd lt days month ) ? dd 1 // end function
setDate
68Date.cpp (2/5)
// overloaded prefix increment operator Date
Dateoperator() 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
Dateoperator( 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
69Date.cpp (3/5)
// add specified number of days to date const
Date Dateoperator( int additionalDays )
for ( int i 0 i lt additionalDays i )
helpIncrement() return this // enables
cascading // end function operator // if the
year is a leap year, return true otherwise,
return false bool DateleapYear( 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 DateendOfMonth( 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
70Date.cpp (4/5)
// function to help increment the date void
DatehelpIncrement() // day is not end of
month if ( !endOfMonth( day ) ) day
// increment day else if ( month lt 12 )
// day is end of month and month lt 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
71Date.cpp (5/5)
// overloaded output operator ostream
operatorltlt( ostream output, const Date d )
static char monthName 13 "", "January",
"February", "March", "April", "May",
"June", "July", "August", "September",
"October", "November", "December" output ltlt
monthName d.month ltlt ' ' ltlt d.day ltlt ", " ltlt
d.year return output // enables cascading
// end function operatorltlt
72datetester.cpp
Date d1 // defaults to January 1, 1900 Date d2(
12, 27, 1992 ) // December 27, 1992 Date d3( 0,
99, 8045 ) // invalid date cout ltlt "d1 is " ltlt
d1 ltlt "\nd2 is " ltlt d2 ltlt "\nd3 is " ltlt d3 cout
ltlt "\n\nd2 7 is " ltlt ( d2 7 ) d3.setDate(
2, 28, 1992 ) cout ltlt "\n\n d3 is " ltlt d3 cout
ltlt "\nd3 is " ltlt d3 ltlt " (leap year allows
29th)" Date d4( 7, 13, 2002 ) cout ltlt
"\n\nTesting the prefix increment operator\n
ltlt " d4 is " ltlt d4 ltlt endl cout ltlt "d4 is "
ltlt d4 ltlt endl cout ltlt " d4 is " ltlt d4 cout
ltlt "\n\nTesting the postfix increment
operator\n ltlt " d4 is " ltlt d4 ltlt
endl cout ltlt "d4 is " ltlt d4 ltlt endl cout ltlt
" d4 is " ltlt d4 ltlt endl
Demonstrate prefix increment
Demonstrate postfix increment
73datetester.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