40
OOP Egar 2008 – Recitation 4 1 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

  • View
    215

  • Download
    1

Embed Size (px)

Citation preview

Page 1: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 1

Object Oriented Programming

Spring 2006Recitation 6

Page 2: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 2

Friends

Page 3: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 3

Non-member Private Access

• Sometimes we need to “break” the encapsulation of a class – allow a non-member function access to private parts.

• For example, operator+() should not be a member function, but it might need access to implementation.

• C++ allows the class to declare some function as its friend, thus allowing access to private parts.

Page 4: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 4

Friend Function• Adding keyword friend before function name in a

class definition implies that this function is friend of the class rather than member. The function still needs to be defined.

class Complex {friend const Complex

operator+(const Complex&, const Complex&);

};

• operator+() above is not a member function of Complex (we can’t call c.operator+() for Complex c), but it can access private parts of Complex.

Page 5: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 5

Friend Class• A class can declare another class’s method as

friend:class A {

friend void B::stop();};class B {

void stop();};

• If all methods of one class need to be friends of another, the whole class can be declared friend:

class A {friend class B;

};

Page 6: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 6

Technicalities• friendship is not transitive. A friend of a

friend is not (necessarily) a friend.• It doesn’t matter if the friend declaration is

made in the public or private parts (public is better).

• If the friend function is itself a method of another class, it doesn’t matter if it is in the public or private parts.

• Don’t declare everything friend just because you can.

Page 7: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 7

Operator Overloading

Page 8: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 8

The “Old” Matrix• Consider class Matrix that implements a 2D

matrix of integers.• It supports all the usual operations –

arithmetics, printing, indexing, assigning.• Its use looks like:

Matrix m1, m2, m3;m3.copy(m1);m3.add(m2);m3.print();cout << m1.index(5, 5);

Page 9: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 9

The “New” Matrix• It’s much more natural to use standard

notation: +, *, <<, =…• These are called operators, and in C++

the programmer can define new meanings for them – this is called operator overloading.

• Now the usage is more natural: Matrix m1, m2, m3;m3 = m1 + m2;cout << m3;cout << m1(5, 5);

Page 10: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 10

Syntax• An overloaded operator is simply a function with

funny name and calling syntax. It can implement any behavior we want (+ can subtract, etc.)

• Name for the function that implements + isoperator+()

and it can be called either bym1 + m2;

or byoperator+(m1, m2);

Basically, the compiler replaces the former form by the latter.

Page 11: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 11

Two Forms of An Operator

• Just as any function, an operator can be defined as a non-member function, or as a class method.

• If a compiler seesm1 + m2;

it looks for operator+ in m1’s class and writesm1.operator+(m2);

and for non-member operator+ and writesoperator+(m1, m2);

• If both exist, overloading resolution is used.

Page 12: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 12

Binary and Unary• A binary operator takes two arguments

(such as +, -, <).• A unary operator takes one argument

(such as ++, !).

Page 13: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 13

Overloadable Binary• These binary operators can be

overloaded:+ - * / %

& | ^

= += -= *= /= %= <<=

>>=

&= |= ^=

< <= > >= == !=

[] ()

->* -> ,

<< >> && ||

Page 14: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 14

Overloadable Unary• These unary operators can be overloaded:

~ ! - +

& * new new[] delete delete[]

++ (prefix) ++ (postfix) -- (prefix) -- (postfix)

Page 15: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 15

Non-overloadable• These operators cannot be overloaded:

:: . .* sizeof typeid ?:

Page 16: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 16

Binary Looks and Calling• A binary operator can be defined by either

– a non-static member function taking one argument of any type,

– or a non-member function taking two arguments of any type.

• Return type can be anything.• For a binary operator@, a@b can be

interpreted either as a.operator@(b) or as operator@(a, b).

Page 17: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 17

Unary Looks and Calling• A unary operator can be defined by either

– a non-static member function taking no arguments,

– or a non-member function taking one argument of any type.

• Return type can be anything.• For a unary operator@, @a can be interpreted

either as a.operator@() or as operator@(a).

Page 18: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 18

Must-be Members• These operators must be non-static

member functions of a class:– operator=– operator[]– operator()– operator->

• This is to ensure that their first operand is lvalue.

• All the rest can be either member or non-member.

Page 19: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 19

Example Implementation

Class TextNum

Page 20: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 20

TextNum’s Description• Let’s implement a class that holds a text

description of an integer.• A TextNum can be printed, assigned to,

added/multiplied (etc.), compared, incremented, negated, indexed, and more…

Page 21: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 21

Basic Definitionclass TextNum {public: TextNum(int); TextNum(const TextNum&); int to_int() const; string to_string() const;private: string _textNum; int _num; string intToString(int);};

Page 22: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 22

Binary Operator+()const TextNum operator+ (const

TextNum& lhs,

const TextNum& rhs)

{ return lhs.to_int() + rhs.to_int();}

Page 23: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 23

Commutativity andImplicit Conversions

• If operator+ is a member function, we have a problem:TextNum t1;int i;t1 + i; // FINE, means

t1.operator+(i), i is // implicitly converted to TextNum

i + t1; // ERROR, not int::operator+() nor// operator+(TextNum,TextNum) exist

• Making an operator a non-member function allows implicit type conversions on the first argument:

t1 + i; // operator+(t1, i)i + t1; // operator+(i, t1)

// both times i is implicitly// converted to TextNum

Page 24: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 24

Operator==()bool operator== (const TextNum&

lhs,

const TextNum& rhs){ return lhs.to_int() == rhs.to_int();}

Page 25: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 25

Operator<<()ostream& operator<< (ostream&

output,

const TextNum& rhs)

{ output << rhs.to_string(); return output;}

Page 26: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 26

Operator<<() as Non-member

• Shifting operator (>>, <<) are commonly used in C++ for input/output operations.

• operator<<() need not be commutative, but still we declare it non-member.

• This is because otherwise it would have to be called like this:

t1 << cout; // t1.operator<<(cout);

Page 27: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 27

Unary Operator-()TextNum TextNum::operator-(){ return -_num;}

Page 28: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 28

Prefix and PostfixOperator++()

// PrefixTextNum& TextNum::operator++(){ _textNum = intToString(++_num); return *this;}

// Postfixconst TextNum TextNum::operator++(int){ TextNum old = *this; ++(*this); return old;}

Page 29: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 29

Prefix and Postfix• Unary operator++() and operator--() can be

either prefix (++i) or postfix (i++).• Overloaded postfix operator has a dummy

int parameter that is not used.• Prefix operator should return a reference

to this, while postfix should return a const copy of the old state.

Page 30: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 30

Operator=() and Operator+=()

TextNum& TextNum::operator=(const TextNum& rhs)

{ _num = rhs._num; _textNum = rhs._textNum; return *this;}

TextNum& TextNum::operator+=(const TextNum& rhs)

{ _num += rhs._num; _textNum = intToString(_num); return *this;}

Page 31: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 31

Assignment• operator=() is called assignment operator.• If it is not defined for a class, compiler will

automatically generate one (if needed).• By a strange turn of fate, operator=() must

be a member function, while operator+=(), etc. can be a non-member function.

• Assignment operators should return a reference to *this.

Page 32: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 32

Assignment operator• Make sure to return a reference to the

objects to allow chaining. May be weird (a=b)=c but this is how int works.

• MAKE SURE TO CHECK FOR SELF ASSIGNMENT!If your class using dynamic allocated data then obj=obj //KABOOM!!!

Page 33: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 33

Operator[]()// non-constchar& TextNum::operator[](size_t idx){ return _textNum[idx];}

// constconst char& TextNum::operator[](size_t

idx) const { return _textNum[idx];}

Page 34: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 34

Subscripting• Operator[]() allows subscripting:

t1[10] = 'M‘;

• Usually, both non-const and const versions should be provided – the former allows changing the contents, while the latter allows access when the object is const.

Page 35: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 35

Operator()()const string TextNum::operator()

(size_t start,

size_t end)

{ return _textNum.substr(start, end-

start+1);}

Page 36: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 36

Function Call• operator()() is called function call operator.

cout << t1(0, 5);

• The above looks just like a call to a function named t1() with arguments 0 and 5. This allows creating functors – objects that act like functions. We will see their use in STL.

• operator()() can have any number of parameters. This allows subscripting with more that one index (useful in matrices, for example).

Page 37: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 37

A Word of WarningNever overload &&, || or ,

• This is because C++ employs short-circuit evaluation of boolean expressions:

char *p;if ( (p!=0) && (strlen(p) > 5) ) …

– If p is 0, strlen() is never called.

• But overloading changes the syntax to function call syntax, and in function call all parameters must be evaluated before the call.

Page 38: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 38

Example TextNum Program

TextNum t1(-1032), t2(32);

cout << t1 << endl; cout << t1 + t2 << endl; ++t1; t2--; if (t1 < t2) { cout << t1 << " is less than " << t2 <<

endl; } else { cout << t1 << " is more than " << t2 <<

endl; } cout << 'Z' << (t1 + t2 + 1000)(1,3) <<

endl;

Page 39: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 39

Outputminus one thousand thirty twominus one thousandminus one thousand thirty one is less than thirty

oneZero

Page 40: OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6

OOP Egar 2008 – Recitation 4 40

More on operator overloading

• Here: http://www.parashift.com/c++-faq-lite/operator-overloading.html