1 / 22

Operator Overloading

Operator Overloading. Strong Suggestion : Go over the Array class example in Section 8.8 of your text. (You may ignore the Array copy constructor for now.). Review -- Function Signatures. A function signature is what the compiler and linker use to identify a function.

idalia
Download Presentation

Operator Overloading

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Operator Overloading Strong Suggestion: Go over the Array class example in Section 8.8 of your text. (You may ignore the Array copy constructor for now.)

  2. Review -- Function Signatures • A function signature is what the compiler and linker use to identify a function. • In C, functions are identified only by their name. • In C++, a function’s signature includes its name, parameters, and (for member functions) const. It does NOT include the return type.

  3. A C++ swap( ) Function • We still need separate functions, but they can all have the same name. • void swap (int& a, int& b); • void swap (double& a, double& b); • void swap (struct bob& a, struct bob& b);

  4. Operator Overloading Overview • Many C++ operator are already overloaded for primitive types. Examples: + - * / << >> • It is often convenient for our classes to imitate the operations available on primitive types (e.g., + or - ). • Then we can use the same concise notation for manipulating our objects.

  5. A Complex Number Class class Complex {public: Complex (int real = 0, int imagine = 0); int getReal ( ) const; int getImagine ( ) const; void setReal (int n); void setImagine (int d); private: int real; int imagine; };

  6. Using Complex Class • It makes sense to want to perform mathematical operations with Complex objects. Complex C1 (3, 5), C2 (5, 9), C3; C3 = C1 + C2; // addition C2 = C3 * C1; // subtraction C1 = -C2; // negation

  7. Operators Are Really Functions • For user-defined types, when you use an operator, you are making a function call. • Consider the expression: C2 + C1 • This is translated into a function call. • The name of the function is “operator+” • The call is: C2.operator+(C1);

  8. Declaring operator+ As a Member Function class Complex { public: const Complex operator+ (const Complex &rhs) const; … }; • Note all of the const’s!

  9. operator+ Implementation const Complex Complex :: operator+ (const Complex &rhs) const { Complex sum; // accessor and mutators not required sum.imagine = imagine + rhs.imagine; // but preferred sum.setReal( getReal( ) + rhs.getReal ( ) ); return sum; }

  10. Using operator+ • We can now write C3 = C2 + C1; • We can also use cascading operators. C4 = C3 + C2 + C1; • And we can write C3 = C2 + 7; • But C3 = 7 + C2 is a compiler error. (Why?)

  11. operator+ As aNon-member, Non-friend const Complex operator+ (const Complex &lhs, // extra parameter const Complex &rhs) // not const { // must use accessors and mutators Complex sum; sum.setImagine (lhs.getImagine( ) + rhs.getImagine( ) ); sum.setReal (lhs.getReal ( ) + rhs.getReal( ) ); return sum; } // is now commutative

  12. Declaring operator+As a Non-member Friend • Declare operator+ as a friend in the class definition. class Complex { public: friend const Complex operator+ (const Complex& a, const Complex& b); … };

  13. Operator+ As aNon-member Friend (con’t) const Complex operator+ (const Complex& lhs, const Complex& rhs) { Complex sum; // accessors and mutators not required sum.imagine = lhs.imagine + rhs.imagine; // but preferred sum.setReal( lhs.getReal( ) + rhs.getReal( )) ; return sum; } // violates encapsulation! Non-friend better.

  14. Printing Objects • Each object should be responsible for printing itself. • This guarantees objects are always printed the same way. • It allows us to write intuitive output code: Complex C5 (5, 3); cout << C5 << endl;

  15. Operator<< • The insertion operator << is a function and can (and should) be overloaded. We can do operator>>, too. • << is a binary operator. • The left-hand operand is of type ostream& • Therefore, operator<< cannot be a member function. It must be a non-member.

  16. operator<< ostream& operator<< (ostream& out, const Complex& c) { out << c.getReal( ); int imagine = c.getImagine( ); out << (imagine < 0 ? “ - ” : “ + ” ) out << imagine << “i”; return out; } • Could be, and often, is a friend • Note: no endl

  17. Operator<< Returns Type ‘ostream &’ • Why? So we can write statements such as cout << C5 << “is a complex number” OR cout << C3 << endl << C2 << endl; • << associates from left to right.

  18. Overloading Unary Operators Complex C1(4, 5), C2; C2 = -C1; is an example of a unary operator (minus). • We can and should overload this operator as a member function.

  19. Unary operator- const Complex Complex :: operator- ( ) const { Complex x; x.real = -real; x.imagine = imagine; return x; }

  20. Overloading = • Remember that assignment performs a memberwise (shallow) copy by default. • This is not sufficient when a data member is dynamically allocated. • = must be overloaded to do a deep copy.

  21. Restrictions • Not all operators can be overloaded. • You can’t make up your own operators. • You can’t overload operators for primitive types (like int). • You can’t change the precedence of an operator. • You can’t change the associativity of an operator.

  22. Good Programming Practices • Overload operators so that they mimic the behavior of primitive data types. • Overloaded binary arithmetic operators should • return const objects by value • be written as non-member functions when appropriate to allow commutativity • be written as non-friend functions (if data member accessors are available) • Overload unary operators as member functions. • Always overload << • Always overload = for objects with dynamic data members.

More Related