1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member...

35
1 159.234 159.234 LECTURE 13 LECTURE 13 Operator Overloading Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators • Postfix/infix increment operator • Binary operators overloading • Overloading I/O operators

Transcript of 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member...

Page 1: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

1

159.234159.234 LECTURE 13LECTURE 13

Operator OverloadingOperator Overloading

Textbook p.203—216

Today:const member functions Overloading Operators

• Postfix/infix increment operator • Binary operators overloading• Overloading I/O operators

Page 2: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

2

A member function that is notnot allowed to modify data members of its class is declared as a constconst member function.

class Point { public: Point(): x(0),y(0){}; Point(int a,int b){x = a;y = b;} void print() constconst; private: int xx, yy;};void Point::print() constconst { cout <<" x = " << x <<", y = " << y;}

constconst Member Functions Member Functions

Page 3: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

3

CORRECT:

void Point::print() constconst{ cout <<" x = " << x <<", y = " << y;}

WRONG:void Point::print() constconst{ x=4;x=4; cout <<" x = " << x <<", y = " << y;}

Error message: Cannot modify a const object.

constconst Member Functions Member Functions

Page 4: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

4

Operator OverloadingOperator Overloading

We have already seen Function overloading.

Operators + -+ - etc, can also be re-defined!

User-defined 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 functionsfunctions:

-x -> negate(x)x+y -> add(x,y)

with operator overloading, we use 'natural operatorsnatural operators’ rather than having to use functions.

Page 5: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

5

Operator OverloadingOperator OverloadingWe can overload:

arithmetic+ - etclogical&& ||comparison> == etcassignment

=index

[]function

()structure pointer

->

new, delete

Only 44 operators cannotcannot be overloaded:

dot .conditional ?:scope ::

sizeof

Page 6: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

6

Operator OverloadingOperator Overloading

Although the semantics of an operator can be extended, we cannot change its syntax, the grammatical rules that governits use, such as the number of operands, precedence and associativity remains the same.

e.g.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.e.g. An operator+operator+ that is overloaded to add two vectors, can stillbe used to add two integers.

Page 7: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

7

Defining Operator OverloadingDefining Operator Overloading

To define an additional task to an operator, we must specify what itmeans 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 typereturn type classname :: operator (op-arglist){ function body //task defined}

Operator being overloaded

operator is the function name

Page 8: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

8

Binary Operator OverloadingBinary Operator Overloading

class clock {public: clock(int seconds=0) : total(seconds) {} clock operator+operator+(int seconds) { clock temp; temp.total = total + seconds; return temp; } void print(void) {cout << total << endl;}

private: int totaltotal;}; ... clock a(50), b; b = b = a + a + 10;10; b.print();

e.g. overloading the + operator:

There is an implicit first implicit first argumentargument (the thisthis pointer). It takes some time to get used to it.

Using a member function

Allows only expressions with an object on the left-hand side of the operator

Page 9: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

9

Binary Operator OverloadingBinary Operator Overloading

class clock {public: clock(int seconds=0) : total(seconds) {} //for construction and conversion friend clock operator+operator+(clock c1, clock c2); void print(void) {cout << total << endl;}

private: int total;};

clock operator+operator+(clock c1, clock c2){ return (c1.total + c2.total);}

e.g. overloading the + operator:

It is normal for symmetric Binary operators to be overloaded by friend functions.

Using a friend function

Page 10: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

10

Unary Operator OverloadingUnary Operator Overloadinge.g. overloading the prefix ++ operator:

class clock {public: clock(int seconds=0) : total(seconds) {} clock operator++operator++() { total++; return *this*this; } void print(void) {cout << total << endl;}private: int total;}; ... a = ++b;a = ++b; b.print();

Page 11: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

11

Overloading the postfix ++ OperatorOverloading the postfix ++ Operator

Can we differentiate between prefix and postfix?

In the code previously shown - the compiler uses the overloaded ++ 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 postfixpostfix the compiler uses an 'ad hoc' convention, it tries to find a version of operator++ version of operator++ with an integer argument:with an integer argument:

clock operator++operator++(int) { clock temp = *this*this; total++; return temp; }

The value of the integer is The value of the integer is irrelevant, but it gives us irrelevant, but it gives us the chance to write two the chance to write two different functions.different functions.

Page 12: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

12

Overloading the [ ] Operator Overloading the [ ] Operator

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:

class vect {public: vect(int n) : size(n) { p = new int[size]; assert(p!=NULL); for (int i=0;i<size;i++) { p[i] = 0; } } ~vect() {delete [] p;} int&& operator[][](int i) { assert((i>=0) && (i<size)); return p[i]; }private: int *p; int size;};

Returning a reference to p[i] does not return a copy of p[i], but returns p[i] returns p[i] itself!itself!

Page 13: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

13

Operator OverloadingOperator Overloading

Why does operator[] return an int &int & rather than an intint?

vect v(10); int i;

i = v[0]v[0]; // read the value at v[0];

v[0]v[0] = 3; // write to v[0]!write to v[0]! // we return a referencewe return a reference // so we can alter the valueso we can alter the value

Functions that return references can appear on the left left hand sidehand side of an assignment statement!

Page 14: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

14

Operator OverloadingOperator Overloading

We have seen several examples of how operators can be overloaded – but this is not the whole story.

a a b b //where is an operator +, -+, - , etc

is replaced by the compiler with:

a.operatora.operator(b)(b)

and it then looks to see whether you have written this particular member function.

'thisthis' becomes the lhslhs and bb the rhsrhs.

Page 15: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

15

Operator OverloadingOperator Overloading

It also checks the 'type' of b - so operator can be overloaded.

a.operator(b)

If it cannot find any member function that matches, it replaces the text with:

operator(a,b)

A non-member functionnon-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.

1

2

Page 16: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

16

Operator OverloadingOperator Overloading

We are not allowed to overload operators for the standard types

operator+(int int i, intint 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 clock::operator+operator+(clock y);

or a non-member function:non-member function:

clock operator+operator+(clock x, clock y);

Page 17: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

17

Operator OverloadingOperator Overloading

Suppose we also want to say:

c = a + 10;

This is ok if we have either

clock clock::operator+operator+(int i);

or clock operator+operator+(clock x, int i);

What if we want to say:

c = 1010 + a;

Now we run in to difficulties.

The compiler cannot convert this into a member function because we are not we are not allowed to treat 'int' as a class and overload its operatorsallowed to treat 'int' as a class and overload its operators.

int::operator(clock x);

is wrong!

Page 18: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

18

Operator OverloadingOperator Overloading

The compiler can only try to match:

clock operator+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 make them both non-member functionsboth non-member functions.

Non-member functions cannot access private data!

We must either make them friendsfriends, (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)

Page 19: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

19

Operator OverloadingOperator 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 cadds one to the value of c

a + b

operator+ does notnot change the value of either a or b, it returns their sumtheir sum

Page 20: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

20

Overloading I/O Operators Overloading I/O Operators

cout << 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 ostreamostream), that accepts a clock object as a parameter

cout.operator<<(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 non-member functionfunction to match

operator<<(cout, a);

Page 21: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

21

Operator OverloadingOperator Overloadingclass clock { clock(int seconds=0); friend ostream & operator<<(ostream &out, const clock &x); friend istream & operator>>(istream &in, clock &x); ... unsigned long total;};

ostream && operator<<operator<<(ostream &out, const clock &x) { int h, m, s; h = x.total / 3600; m = (x.total / 60) % 60; s = x.total % 60; out << h << “:” << m << “:” << s;out << h << “:” << m << “:” << s; return out;}

Stream extraction (output) operator

operator<< operator<< (also known as (also known as stream deletion stream deletion operatoroperator)) is usually called several times in a single statement.Consequently, the output of each call to operator<< operator<< cascades into the next call as input. That’s why it needs to return a reference to the output stream (cout).

Note: operator precedence: left to right

Page 22: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

22

Operator OverloadingOperator Overloading

istream & operator>>operator>>(istream &in, clock &x) { int h, m, s; in >> h >> m >> s; in >> h >> m >> s; //input retrieved as h m s x.totalx.total = h*3600 + m*60 + s; return in;}

Stream insertion (input) operator

Page 23: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

23

Operator OverloadingOperator Overloading

Overloading the assignment operator.

The copy constructor is called whenever we • pass an object as an argument, pass an object as an argument, • return an object, or return an object, or • intialise an object with one of the same typeintialise 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.

Page 24: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

24

Operator OverloadingOperator Overloading

When we assign an object to another:

str a, b; a == b;

NO copy constructor is involvedNO 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& str::operator==(const str &x){ delete[] s; s = new char[128]; strcpy(s, x.s); return *this*this;}

Rule of thumb: Any time a class needs an explicit copy constructor definedexplicit copy constructor defined,it also needs an assignment operator assignment operator defined.

Page 25: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

25

Argument TypesArgument 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 pass a reference to an objectreference 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!

Page 26: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

26

Argument TypesArgument Types

The answer is to pass a 'constconst' referencereference 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 Passing a const reference is is more efficient more efficient than passing than passing an an object..

Page 27: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

27

Return TypesReturn TypesThese are again quite complicated. It is tempting to think that the assignment operator does not 'return' anything and so it should be voidvoid

void str::operator=(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=operator= must return an str object. Or to make it more efficient a reference to reference to an str objectan str object.

Associativity of assignment operator: Right

Page 28: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

28

Return TypesReturn TypesShould it return a const reference?

Well surprisingly no!

We may want to stop anyone from writing: (a = b) = c;

but strangely enough this is legalis legal for integers! (i = 3) (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.

Page 29: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

29

Return TypesReturn TypesThere was one final blunder when we overloaded the assignment operator for strings!

a = a;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 & str::operator=(const str &x){ if (&x == this) {if (&x == this) { return *this;return *this; }} delete[] s; s = new char[128]; strcpy(s,x.s); return *this;}

Allows multiple assignment with right-to-left associativity to be defined

Page 30: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

30

Overloading Assignment and Overloading Assignment and Subscripting OperatorsSubscripting Operators

• Must be done as non-static member functions

• Usually involve a reference return type

Common Characteristics

Page 31: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

31

Return TypesReturn Types

Be careful when returning reference types. Consider the case of the prefix ++ operator:

clock& operator++operator++(){ total++; return *this; }

This is okThis is ok, and more efficient than returning a clock object (a constructor would be called!)

Page 32: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

32

Return TypesReturn TypesBut in the case of the postfix ++ operator:

clock& operator++(int) { clock temp = *this; total++; return temp; }

This is wrong!wrong! We are returning a reference to temp, and temp no temp no longer exists!longer exists!

For certain functions we must return an object, not a reference.

const clock operator++(int) { clock temp = *this; total++; return temp; }

Page 33: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

33

Page 34: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

34

Page 35: 1 159.234LECTURE 13 159.234 LECTURE 13 Operator Overloading Textbook p.203—216 Today: const member functions Overloading Operators Postfix/infix increment.

35

Return TypesReturn Types

Postfix ++ is nearly always less efficient than prefix ++ for user defined classes.

view Clock3.cpp

To see demo:To see demo: