159.234 Lecture 10 - PowerPoint PPT Presentation

About This Presentation
Title:

159.234 Lecture 10

Description:

159.234 LECTURE 13 Operator Overloading Today: const member functions Overloading Operators Postfix/infix increment operator Binary operators overloading – PowerPoint PPT presentation

Number of Views:97
Avg rating:3.0/5.0
Slides: 36
Provided by: eca110
Category:

less

Transcript and Presenter's Notes

Title: 159.234 Lecture 10


1
159.234 LECTURE 13
Operator Overloading
  • Today
  • const member functions
  • Overloading Operators
  • Postfix/infix increment operator
  • Binary operators overloading
  • Overloading I/O operators

Textbook p.203216
2
const Member Functions
A member function that is not allowed to modify
data members of its class is declared as a const
member function.
class Point public Point() x(0),y(0)
Point(int a,int b)x ay b void
print() const private int x, y void
Pointprint() const cout ltlt" x " ltlt x
ltlt", y " ltlt y
3
const Member Functions
CORRECT void Pointprint() const cout ltlt" x
" ltlt x ltlt", y " ltlt y
WRONG void Pointprint() const x4 cout ltlt"
x " ltlt x ltlt", y " ltlt y Error message
Cannot modify a const object.
4
Operator Overloading
We have already seen Function overloading. Operat
ors - etc, can also be re-defined! User-define
d types can be treated in exactly the same way as
simple types. e.g. for a 'complex' type we can
allow the addition of two variables. Operators
can be thought of as functions -x -gt negate(x)
xy -gt add(x,y) with operator overloading, we
use 'natural operators rather than having to use
functions.
5
Operator Overloading
We can overload arithmetic - etc logical
comparison gt etc assignment index fu
nction () structure pointer -gt new, delete
Only 4 operators cannot be overloaded dot . co
nditional ? scope sizeof
6
Operator Overloading
Although the semantics of an operator can be
extended, we cannot change its syntax, the
grammatical rules that govern its use, such as
the number of operands, precedence and
associativity remains the same.
e.g. the multiplication operator will enjoy
higher precedence than the addition operator.
When an operator is overloaded, its original
meaning is not lost.
e.g. An operator that is overloaded to add two
vectors, can still be used to add two integers.
7
Defining Operator Overloading
To define an additional task to an operator, we
must specify what it means in relation to the
class to which the operator will be applied.
This is done with the help of a special function
called operator function which describes the task.
General form of an operator function
return type classname operator?
(op-arglist) function body //task defined
Operator being overloaded
operator? is the function name
8
Binary Operator Overloading
e.g. overloading the operator
Using a member function
class clock public clock(int seconds0)
total(seconds) clock operator(int seconds)
clock temp temp.total total
seconds return temp void
print(void) cout ltlt total ltlt endl private
int total ... clock a(50), b b a
10 b.print()
There is an implicit first argument (the this
pointer). It takes some time to get used to it.
Allows only expressions with an object on the
left-hand side of the operator
9
Binary Operator Overloading
e.g. overloading the operator
Using a friend function
class clock public clock(int seconds0)
total(seconds) //for construction and
conversion friend clock operator(clock c1,
clock c2) void print(void) cout ltlt total
ltlt endl private int total clock
operator(clock c1, clock c2) return
(c1.total c2.total)
It is normal for symmetric Binary operators to
be overloaded by friend functions.
10
Unary Operator Overloading
e.g. overloading the prefix operator
class clock public clock(int seconds0)
total(seconds) clock operator()
total return this void
print(void) cout ltlt total ltlt endl private
int total ... a b b.print()
11
Overloading the postfix Operator
Can we differentiate between prefix and
postfix? In the code previously shown - the
compiler uses the overloaded for both postfix
and prefix. To create different prefix and
postfix versions we need some help from the
compiler. The compiler knows whether the code is
prefix or postfix. If it is postfix the compiler
uses an 'ad hoc' convention, it tries to find a
version of operator with an integer argument
The value of the integer is irrelevant, but it
gives us the chance to write two different
functions.
clock operator(int) clock temp
this total return temp
12
Overloading the Operator
class vect public vect(int n) size(n)
p new intsize assert(p!NULL)
for (int i0iltsizei) pi 0
vect() delete p int
operator(int i) assert((igt0)
(iltsize)) return pi private
int p int size
Arrays are often abused. Range violations are
common. Negative indices or indices greater than
the maximum cause programs to access wrong
data. We can create an array class that
overloads , and checks array bounds
Returning a reference to pi does not return a
copy of pi, but returns pi itself!
13
Operator Overloading
Why does operator return an int rather than
an int? vect v(10) int i i v0
// read the value at v0 v0 3 //
write to v0! // we return a
reference // so we can alter
the value Functions that return references can
appear on the left hand side of an assignment
statement!
14
Operator Overloading
We have seen several examples of how operators
can be overloaded but this is not the whole
story. a ? b //where ? is an operator , - ,
etc is replaced by the compiler with
a.operator?(b) and it then looks to see whether
you have written this particular member
function. 'this' becomes the lhs and b the rhs.
15
Operator Overloading
1
a.operator?(b)
It also checks the 'type' of b - so operator? can
be overloaded.
If it cannot find any member function that
matches, it replaces the text with
operator?(a,b) A non-member function, with two
arguments, and tries again to find a match in the
functions you have defined. You may choose to
use either way.
2
16
Operator Overloading
We are not allowed to overload operators for the
standard types operator(int i, int j)
will not work. This leads to some
difficulties. Suppose we have a clock class, and
want to be able to say clock a,b,c c a
b This works if we have either a member
function of clock clock clockoperator(clock
y) or a non-member function clock
operator(clock x, clock y)
17
Operator Overloading
Suppose we also want to say c a
10 This is ok if we have either clock
clockoperator(int i) or clock
operator(clock x, int i) What if we want to
say c 10 a Now we run in to
difficulties. The compiler cannot convert this
into a member function because we are not allowed
to treat 'int' as a class and overload its
operators. intoperator(clock x) is wrong!
18
Operator Overloading
The compiler can only try to match clock
operator(int i, clock x) We have lost
symmetry. If we want to allow 10 a as well as
a 10 then it is neater to make them both
non-member functions. Non-member functions
cannot access private data! We must either make
them friends, (frowned on, perhaps) or
provide functions to access the data get()
and set() routines, or whatever we want to call
them (better but more work)
19
Operator Overloading
Remember that some operators change the value of
one of their arguments, and others do
not. c the increment operator adds
one to the value of c a b operator does not
change the value of either a or b, it returns
their sum
20
Overloading I/O Operators
cout ltlt a Can we overload the output
operator? Yes but remember that the compiler
first tries to find a member function of the
ostream class (cout is an object of ostream),
that accepts a clock object as a parameter
cout.operatorltlt(a) The writer of the ostream
class will not have included this function! And
you cannot add it. Our only option is to supply
the compiler with a non-member function to
match operatorltlt(cout, a)
21
Operator Overloading
class clock clock(int seconds0) friend
ostream operatorltlt(ostream out, const clock
x) friend istream operatorgtgt(istream in,
clock x) ... unsigned long
total ostream operatorltlt(ostream out,
const clock x) int h, m, s h
x.total / 3600 m (x.total / 60) 60 s
x.total 60 out ltlt h ltlt ltlt m ltlt ltlt
s return out
Stream extraction (output) operator
Note operator precedence left to right
operatorltlt (also known as stream deletion
operator) is usually called several times in a
single statement. Consequently, the output of
each call to operatorltlt cascades into the next
call as input. Thats why it needs to return a
reference to the output stream (cout).
22
Operator Overloading
Stream insertion (input) operator
istream operatorgtgt(istream in, clock x)
int h, m, s in gtgt h gtgt m gtgt s //input
retrieved as h m s x.total h3600 m60
s return in
23
Operator Overloading
  • Overloading the assignment operator.
  • The copy constructor is called whenever we
  • pass an object as an argument,
  • return an object, or
  • intialise an object with one of the same type
  • There is a need for a copy constructor because
    the default system copy constructor performs only
    shallow copy, and is not normally adequate when
    pointers are involved.
  • Therefore, we need to perform a deep copy to copy
    what the pointers are pointing to.

24
Operator Overloading
When we assign an object to another str a,
b a b NO copy constructor is involved. It
is an assignment. If we want assignment to behave
like a deep copy constructor, we need to overload
the assignment operator. str
stroperator(const str x) delete s s
new char128 strcpy(s, x.s) return
this
Rule of thumb Any time a class needs an
explicit copy constructor defined, it also needs
an assignment operator defined.
25
Argument Types
Argument types. You may always pass objects as
arguments sometimes we really want to but
most times, if we do, they lead to very
inefficient code. If you pass across an object a
copy constructor will be called. Instead of
passing an object most of the time we pass a
reference to an object instead. Only a pointer is
copied! However, passing a reference is not
normally acceptable. If the actual argument to a
function is a constant, then the compiler will
not let you pass it to a reference parameter
the function may try to change the value of a
constant!
26
Argument Types
The answer is to pass a 'const' reference
parameter. Now the compiler can check that the
function does not change its value (it will
complain if it does try to) and constant can
safely be passed in the knowledge that they can't
be changed. Passing a const reference is more
efficient than passing an object.
27
Return Types
These are again quite complicated. It is tempting
to think that the assignment operator does not
'return' anything and so it should be void void
stroperator(str x) However this is NOT
correct. It is perfectly correct to write a
b c which is the same as a (b
c) (b c) has the 'value' of a. operator
must return an str object. Or to make it more
efficient a reference to an str object.
Associativity of assignment operator Right
28
Return Types
Should it return a const reference? Well
surprisingly no! We may want to stop anyone from
writing (a b) c but strangely enough
this is legal for integers! (i 3)
2 first it assigns 3 to i and then assigns 2 to
i And if we can do it with integers we should be
allowed to do it with strings.
29
Return Types
There was one final blunder when we overloaded
the assignment operator for strings! a
a Isn't very sensible, but it is legal. A
program that uses our str class will fail if this
statement occurs. We must modify our function as
follows str stroperator(const str x)
if (x this) return this
delete s s new char128
strcpy(s,x.s) return this
Allows multiple assignment with right-to-left
associativity to be defined
30
Overloading Assignment and Subscripting Operators
Common Characteristics
  • Must be done as non-static member functions
  • Usually involve a reference return type

31
Return Types
Be careful when returning reference types.
Consider the case of the prefix operator
clock operator() total return
this This is ok, and more efficient than
returning a clock object (a constructor would be
called!)
32
Return Types
But in the case of the postfix operator
clock operator(int) clock temp
this total return temp
This is wrong! We are returning a reference
to temp, and temp no longer exists! For certain
functions we must return an object, not a
reference. const clock operator(int)
clock temp this total return
temp
33
(No Transcript)
34
(No Transcript)
35
Return Types
Postfix is nearly always less efficient than
prefix for user defined classes.
view Clock3.cpp
To see demo
Write a Comment
User Comments (0)
About PowerShow.com