1 / 26

Operator Overloading

Learn about the use of operator overloading in C++, including the "swap" function for different data types and complex number operations.

lkraus
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

  2. The ‘C’ swap() function • In ‘C’ we need a “swap” function for each different data type • void swapInt (int* a, int* b); • void swapDbl (double* a, double* b); • void swapBob (struct bob* a, struct bob* b) • etc., etc., etc. • Why??

  3. 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); • Is this an improvement? • Why can I do this in C++ and not C?

  4. Function signatures • A function signature is what the compiler/linker uses to identify a function • In C, functions are identified only by their name • In C++, function signatures include name, parameters and, (for member functions) const --- NOT return type

  5. Constructors are functions too Recall that we can create (declare) a file as an ifstream two ways --- • ifstream fileA; • ifstream fileB (“filename”); • These use different constructors • ifstream ( ); • ifstream (char * filename);

  6. Operator Overloading Overview • Classes allow us to define our own data types in addition to the built in primitive types. • It’s often convenient for our classes to model the operations available on primitive types. • We can use the same concise notation for expressing how to manipulate our objects.

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

  8. Complex (cont’d) private: int real; int imagine; };

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

  10. 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+”

  11. operator+ as a member function • What’s the full name of the function? • What should the return type be? • What are the parameters? (trick question) • Should it be const?

  12. Declaring operator+ as a member function class Complex { public: const Complex operator+ (const Complex& rhs) const; ….. }; • Why just one parameter?????

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

  14. Using operator+ • We can now write (cascading operators) C4 = C3 + C2 + C1; • We can also write (how does it work?) C3 = C2 + 7; • But C3 = 7 + C2 is a compiler error (Why?)

  15. Operator+ as a non-member (ordinary old) function • What’s the full name of the function? • What should the return type be? • What are the parameters? • ‘const’ does not apply to non-member functions

  16. operator+non-member, non-friend const Complex operator+ (const Complex& lhs, const Complex& rhs) { // must use accessors and mutators Complex sum; sum.setImagine (lhs.getImagine( ) + rhs.getImagine( ) ); sum.setReal (lhs.getReal ( ) + rhs.getReal( ) ); return sum; }

  17. Declaring operator+as non-member friend • Declare operator+ as a friend in class definition class Complex { public: friend const Complex operator+ (const Complex& a, const Complex& b); …. };

  18. Operator+ asnon-member friend 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; }

  19. 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;

  20. Operator<< • The insertion operator << is a function and can (and should) be overloaded. We can do operator>> too. • What are the parameters to the operator<< function call when we write cout << C5; • What does this imply?

  21. 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

  22. Operator<< returns ‘ostream &’ • Why? • So we can write cout << C5 << “is a complex number” • This is really a set of nested function calls Operator<< (operator<<(cout, C5), “…..”);

  23. Overloading unary operators Complex C1(4, 5), C2; C2 = -C1; Is an example of a unary operator (minus) We can and should overload as member

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

  25. 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 associativity • You can change the number of operands

  26. Good Programming Practices • Overloaded binary arithmetic operators should • Return const objects by value • Be written as non-member functions when appropriate to allow commutativity • Overload unary operators as members • Always overload operator<< • Overload operators so that they mimic the behavior of primitive data types

More Related