OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6.
-
date post
22-Dec-2015 -
Category
Documents
-
view
215 -
download
1
Transcript of OOP Egar 2008 – Recitation 41 Object Oriented Programming Spring 2006 Recitation 6.
OOP Egar 2008 – Recitation 4 1
Object Oriented Programming
Spring 2006Recitation 6
OOP Egar 2008 – Recitation 4 2
Friends
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.
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.
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;
};
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.
OOP Egar 2008 – Recitation 4 7
Operator Overloading
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);
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);
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.
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.
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 ++, !).
OOP Egar 2008 – Recitation 4 13
Overloadable Binary• These binary operators can be
overloaded:+ - * / %
& | ^
= += -= *= /= %= <<=
>>=
&= |= ^=
< <= > >= == !=
[] ()
->* -> ,
<< >> && ||
OOP Egar 2008 – Recitation 4 14
Overloadable Unary• These unary operators can be overloaded:
~ ! - +
& * new new[] delete delete[]
++ (prefix) ++ (postfix) -- (prefix) -- (postfix)
OOP Egar 2008 – Recitation 4 15
Non-overloadable• These operators cannot be overloaded:
:: . .* sizeof typeid ?:
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).
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).
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.
OOP Egar 2008 – Recitation 4 19
Example Implementation
Class TextNum
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…
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);};
OOP Egar 2008 – Recitation 4 22
Binary Operator+()const TextNum operator+ (const
TextNum& lhs,
const TextNum& rhs)
{ return lhs.to_int() + rhs.to_int();}
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
OOP Egar 2008 – Recitation 4 24
Operator==()bool operator== (const TextNum&
lhs,
const TextNum& rhs){ return lhs.to_int() == rhs.to_int();}
OOP Egar 2008 – Recitation 4 25
Operator<<()ostream& operator<< (ostream&
output,
const TextNum& rhs)
{ output << rhs.to_string(); return output;}
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);
OOP Egar 2008 – Recitation 4 27
Unary Operator-()TextNum TextNum::operator-(){ return -_num;}
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;}
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.
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;}
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.
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!!!
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];}
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.
OOP Egar 2008 – Recitation 4 35
Operator()()const string TextNum::operator()
(size_t start,
size_t end)
{ return _textNum.substr(start, end-
start+1);}
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).
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.
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;
OOP Egar 2008 – Recitation 4 39
Outputminus one thousand thirty twominus one thousandminus one thousand thirty one is less than thirty
oneZero
OOP Egar 2008 – Recitation 4 40
More on operator overloading
• Here: http://www.parashift.com/c++-faq-lite/operator-overloading.html