Object Oriented Programming Spring 2006 Recitation 6 OOP
Object Oriented Programming Spring 2006 Recitation 6 OOP Egar 2008 – Recitation 4 1
Friends OOP Egar 2008 – Recitation 4 2
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 3
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&); }; • 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. operator+() OOP Egar 2008 – Recitation 4 4
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 5
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 6
Operator Overloading OOP Egar 2008 – Recitation 4 7
The “Old” Matrix • • • Consider class Matrix that implements a 2 D matrix of integers. It supports all the usual operations – arithmetics, printing, indexing, assigning. Its use looks like: Matrix m 1, m 2, m 3; m 3. copy(m 1); m 3. add(m 2); m 3. print(); cout << m 1. index(5, 5); OOP Egar 2008 – Recitation 4 8
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 m 1, m 2, m 3; m 3 = m 1 + m 2; cout << m 3; cout << m 1(5, 5); OOP Egar 2008 – Recitation 4 9
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 + is operator+() and it can be called either by m 1 + m 2; or by operator+(m 1, m 2); Basically, the compiler replaces the former form by the latter. OOP Egar 2008 – Recitation 4 10
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 sees m 1 + m 2; it looks for operator+ in m 1’s class and writes m 1. operator+(m 2); and for non-member operator+ and writes operator+(m 1, m 2); • If both exist, overloading resolution is used. OOP Egar 2008 – Recitation 4 11
Binary and Unary • • A binary operator takes two arguments (such as +, -, <). A unary operator takes one argument (such as ++, !). OOP Egar 2008 – Recitation 4 12
Overloadable Binary • These binary operators can be overloaded: + - & = += -= *= /= < <= > << >> [] ->* * / % | ^ %= <<= >>= &= |= ^= >= == != && || () -> , OOP Egar 2008 – Recitation 4 13
Overloadable Unary • These unary operators can be overloaded: ~ & ++ (prefix) ! * new ++ (postfix) new[] -- (prefix) OOP Egar 2008 – Recitation 4 delete + delete[] -- (postfix) 14
Non-overloadable • These operators cannot be overloaded: : : . . * sizeof OOP Egar 2008 – Recitation 4 typeid ? : 15
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 16
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 17
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 nonmember. OOP Egar 2008 – Recitation 4 18
Example Implementation Class Text. Num OOP Egar 2008 – Recitation 4 19
Text. Num’s Description • • Let’s implement a class that holds a text description of an integer. A Text. Num can be printed, assigned to, added/multiplied (etc. ), compared, incremented, negated, indexed, and more… OOP Egar 2008 – Recitation 4 20
Basic Definition class Text. Num { public: Text. Num(int); Text. Num(const Text. Num&); int to_int() const; string to_string() const; private: string _text. Num; int _num; string int. To. String(int); }; OOP Egar 2008 – Recitation 4 21
Binary Operator+() const Text. Num operator+ (const Text. Num& lhs, const Text. Num& rhs) { return lhs. to_int() + rhs. to_int(); } OOP Egar 2008 – Recitation 4 22
• Commutativity and Implicit Conversions If operator+ is a member function, we have a problem: Text. Num t 1; int i; t 1 + i; i + t 1; • // // FINE, means t 1. operator+(i), i is implicitly converted to Text. Num ERROR, not int: : operator+() nor operator+(Text. Num, Text. Num) exist Making an operator a non-member function allows implicit type conversions on the first argument: t 1 + i; i + t 1; // // operator+(t 1, i) operator+(i, t 1) both times i is implicitly converted to Text. Num OOP Egar 2008 – Recitation 4 23
Operator==() bool operator== (const Text. Num& lhs, const Text. Num& rhs) { return lhs. to_int() == rhs. to_int(); } OOP Egar 2008 – Recitation 4 24
Operator<<() ostream& operator<< (ostream& output, const Text. Num& rhs) { output << rhs. to_string(); return output; } OOP Egar 2008 – Recitation 4 25
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: t 1 << cout; // t 1. operator<<(cout); OOP Egar 2008 – Recitation 4 26
Unary Operator-() Text. Num: : operator-() { return -_num; } OOP Egar 2008 – Recitation 4 27
Prefix and Postfix Operator++() // Prefix Text. Num& Text. Num: : operator++() { _text. Num = int. To. String(++_num); return *this; } // Postfix const Text. Num: : operator++(int) { Text. Num old = *this; ++(*this); return old; } OOP Egar 2008 – Recitation 4 28
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 29
Operator=() and Operator+=() Text. Num& Text. Num: : operator=(const Text. Num& rhs) { _num = rhs. _num; _text. Num = rhs. _text. Num; return *this; } Text. Num& Text. Num: : operator+=(const Text. Num& rhs) { _num += rhs. _num; _text. Num = int. To. String(_num); return *this; } OOP Egar 2008 – Recitation 4 30
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 31
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 32
Operator[]() // non-const char& Text. Num: : operator[](size_t idx) { return _text. Num[idx]; } // const char& Text. Num: : operator[](size_t idx) const { return _text. Num[idx]; } OOP Egar 2008 – Recitation 4 33
Subscripting • Operator[]() allows subscripting: t 1[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 34
Operator()() const string Text. Num: : operator()(size_t start, size_t end) { return _text. Num. substr(start, end-start+1); } OOP Egar 2008 – Recitation 4 35
Function Call • operator()() is called function cout << t 1(0, 5); call operator. • The above looks just like a call to a function named t 1() 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 36
A Word of Warning Never 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 parameters must be evaluated before the call. OOP Egar 2008 – Recitation 4 37
Example Text. Num Program Text. Num t 1(-1032), t 2(32); cout << t 1 << endl; cout << t 1 + t 2 << endl; ++t 1; t 2 --; if (t 1 < t 2) { cout << t 1 << " is less than " << t 2 << endl; } else { cout << t 1 << " is more than " << t 2 << endl; } cout << 'Z' << (t 1 + t 2 + 1000)(1, 3) << endl; OOP Egar 2008 – Recitation 4 38
Output minus one thousand thirty two minus one thousand thirty one is less than thirty one Zero OOP Egar 2008 – Recitation 4 39
More on operator overloading • Here: http: //www. parashift. com/c++-faqlite/operator-overloading. html OOP Egar 2008 – Recitation 4 40
- Slides: 40