Operator Overloading Version 1.0. Objectives At the end of this lesson, students should be able to: Write programs that correctly overload operators Describe.

Slides:



Advertisements
Similar presentations
Chapter 11 Operator Overloading; String and Array Objects Chapter 11 Operator Overloading; String and Array Objects Part I.
Advertisements

Operator Overloading Fundamentals
Chapter 14: Overloading and Templates C++ Programming: Program Design Including Data Structures, Fifth Edition.
Rossella Lau Lecture 10, DCO10105, Semester B, DCO10105 Object-Oriented Programming and Design  Lecture 10: Operator overload  Operator overload.
 2006 Pearson Education, Inc. All rights reserved Operator Overloading.
© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved. Chapter 18 - C++ Operator Overloading Outline 18.1Introduction.
Chapter 14: Overloading and Templates
Operator Overloading in C++ Systems Programming. Systems Programming: Operator Overloading 22   Fundamentals of Operator Overloading   Restrictions.
Chapter 13: Overloading.
Templates. Objectives At the conclusion of this lesson, students should be able to Explain how function templates are used Correctly create a function.
Chapter 15: Operator Overloading
Operator OverloadingCS-2303, C-Term Operator Overloading CS-2303 System Programming Concepts (Slides include materials from The C Programming Language,
Operator overloading Object Oriented Programming.
Operator Overloading in C++
C++ Programming: Program Design Including Data Structures, Fourth Edition Chapter 14: Overloading and Templates.
Chapter 18 - Operator Overloading Associate Prof. Yuh-Shyan Chen Dept. of Computer Science and Information Engineering National Chung-Cheng University.
Operator Overloading and Type Conversions
C++ Programming: From Problem Analysis to Program Design, Fourth Edition Chapter 15: Overloading and Templates.
1 Overloading Operators Object-Oriented Programming Using C++ Second Edition 8.
Chapter 8 Friends and Overloaded Operators. Copyright © 2005 Pearson Addison-Wesley. All rights reserved. Slide 2 Overview Friend Function (8.1) Overloading.
CS212: Object Oriented Analysis and Design Lecture 10: Copy constructor.
Case Study - Fractions Timothy Budd Oregon State University.
Operatorsand Operators Overloading. Introduction C++ allows operators to be overloaded specifically for a user-defined class. Operator overloading offers.
Operator Overloads Part2. Issue Provide member +(int) operator Rational + int OK int + Rational Error.
ADTs and C++ Classes Classes and Members Constructors The header file and the implementation file Classes and Parameters Operator Overloading.
Object Oriented Programming with C++/ Session 4/ 1 of 49 Operator Overloading Session 4.
Data Structures Using C++ 2E1 Inheritance An “is-a” relationship –Example: “every employee is a person” Allows new class creation from existing classes.
Overloading Operator MySting Example. Operator Overloading 1+2 Matrix M 1 + M 2 Using traditional operators with user-defined objects More convenient.
Concordia University Department of Computer Science and Software Engineering Click to edit Master title style ADVANCED PROGRAM DESIGN WITH C++ Part 9:
Operator Overloading. Objectives At the conclusion of this lesson, students should be able to Explain what operator overloading is Write code that overloads.
CPSC 252 Operator Overloading and Convert Constructors Page 1 Operator overloading We would like to assign an element to a vector or retrieve an element.
Operator Overloading. Introduction It is one of the important features of C++ language  Compile time polymorphism. Using overloading feature, we can.
Operator Overloading Operator Overloading allows a programmer to define new types from the built-in types. –Operator Overloading is useful for redefining.
 2008 Pearson Education, Inc. All rights reserved Operator Overloading.
Slide 1 Chapter 8 Operator Overloading, Friends, and References.
Chapter 11 Friends and Overloaded Operators. Introduction to function equal // Date.h #ifndef _DATE_H_ #define _DATE_H_ class CDate { public: CDate();
Chapter 8 Operator Overloading.  Operator overloading is considered one of the more useful techniques for improving readability and ease of programming.
C++ Programming: From Problem Analysis to Program Design, Third Edition Chapter 15: Overloading and Templates.
Fall 2015CISC/CMPE320 - Prof. McLeod1 CISC/CMPE320 RAD due Friday in your Wiki. Presentations week 6 – next week. Schedule on next slide. Today: –Operator.
Chapter 13: Overloading and Templates. Objectives In this chapter, you will – Learn about overloading – Become familiar with the restrictions on operator.
Programming Fundamentals. Topics to be covered Today Recursion Inline Functions Scope and Storage Class A simple class Constructor Destructor.
AL-HUSEEN BIN TALAL UNIVERSITY College of Engineering Department of Computer Engineering Object-Oriented Programming Course No.: Fall 2014 Overloading.
Learning Objectives Fundamentals of Operator Overloading. Restrictions of Operator Overloading. Global and member Operator. Overloading Stream-Insertion.
1 CISC181 Introduction to Computer Science Dr. McCoy Lecture 26 Clicker Questions December 3, 2009.
1 CSC241: Object Oriented Programming Lecture No 08.
Object Oriented Programming COP3330 / CGS5409.  Arithmetic Operator Overloading  Increment (++) / Decrement (--)  In-class exercise.
CS212: Object Oriented Analysis and Design Polymorphism (Using C++)
Operator Overloading.
Chapter 18 - C++ Operator Overloading
Object-Oriented Programming (OOP) Lecture No. 16
CSE1002 – Problem Solving with Object Oriented Programming
Operator Overloading.
User-Written Functions
Friend functions, operator overloading
Chapter 13: Overloading and Templates
Templates.
Operator Overloading; String and Array Objects
Object Oriented Programming COP3330 / CGS5409
Object-Oriented Programming (OOP) Lecture No. 16
Chapter 15: Overloading and Templates
Andy Wang Object Oriented Programming in C++ COP 3330
Advanced Program Design with C++
Operator Overloading; String and Array Objects
Operator overloading Dr. Bhargavi Goswami
Operator Overloading, Friends, and References
Operator Overloading.
CISC/CMPE320 - Prof. McLeod
COP 3330 Object-oriented Programming in C++
Operator Overloading; String and Array Objects
Andy Wang Object Oriented Programming in C++ COP 3330
Presentation transcript:

Operator Overloading Version 1.0

Objectives At the end of this lesson, students should be able to: Write programs that correctly overload operators Describe how to overload a unary operator Tell how the compiler differentiates between pre- and post Describe how to overload a binary operator Explain when to use member vs non-member functions Explain when it is necessary to use friend functions Demonstrate how to return values when overloading operators Explain why operator overloading is useful Explain what the compiler generates when it sees an overloaded operator Demonstrate how constructors and overloaded cast operator are used to do conversions

In C++, operators are nothing more than functions, written with a different, but more familiar syntax. Operator Overloading

We use operators to express fundamental operations in a concise and readable way. For example, y = x + y * z; is much easier to read and write than y.assign (x.add (y.multiply(z)));

The standard operators in C++ work on all of the basic data types. However, they do not work on user defined data types. To add two objects of the Length class, we could write a function called add, so we could write lengthThree = lengthTwo.add (lengthOne); But, this is awkward. Wouldn’t it be nicer to be able to write lengthThree = lengthTwo + lengthOne;

We can do this if we overload the + operator so that it works with objects of the Length class.

Example

Define the Length class as … class Length { public: Length( ); private: int feet; int inches; }; The Length class keeps track of a length measurement in feet and inches.

To overload the + operator so that we can add two Length objects together, we write a function of the form: Length operator+ (const Length&); in this case the function returns a Length object. the name of the function is operator+ the function takes a const reference to a Length object as a parameter.

Now, if we write lengthThree = LengthTwo + LengthOne; The compiler looks in the Length class for a function with the prototype Length ::operator+ (const Length&);

and generates code just as if we had written lengthThree = lengthTwo.operator+ (lengthOne); the left hand operand becomes the calling object. the right hand operand becomes the parameter in the function call. LengthThree = lengthTwo + lengthOne

All of the C++ operators can be overloaded except for the following:..* :: ?: sizeof Because of the complexities involved, the overloading of &&, ||, and the comma operator is discouraged.

Key points to remember You cannot change the precedence rule by overloading operators. You cannot change the associativity of an operator by overloading it. It is not possible to create new operators. You cannot change the way that the operators work on the basic data types. You cannot change the “arity” of an operator by overloading it.

Overloading Unary Functions It certainly ought to be possible to overload the increment and decrement operators for the Length class. For example, we would probably like to be able to do the following for a length object lengthOne: lengthOne++;

The “makes sense” Rule A programmer can clearly define what to do inside of the function that overloads an operator. However, it is just good programming practice to be sure that the function makes good sense.

So … what does it mean to increment a Length?

Let’s choose the option of adding one inch to the current Length value. This points out a complexity that we may not have thought of before. Suppose we have a Length object whose value is 3 feet and 11 inches. What happens when we increment this object. Obviously we want the result to be 4 feet. This complicates the code we would write, because we always have to check to see if the addition of one inch results in going to a new number of feet.

Let’s simplify the problem by re-defining the Length class and take advantage of data hiding. class Length { public: Length( ); private: int inches; }; Because we only keep track of inches, we don’t have to worry here (or in any other arithmetic operation) about handling the overflow from inches to feet.

Now the code for the operator++ function would look something like: const Length& Length::operator++( ) { ++inches; return *this; } when written as a member function, functions that overload unary operators take no parameters. the function works on the calling object. In this case, the inches data member of the calling object is incremented. we return the calling object (by reference).

Return Types In the increment example, why did we return a Length object, and why by reference? In any expression, the result of some operation may be used as an operand for another operator. Consider the expression Length someLength = ++lengthOne; in this case, the result of incrementing lengthOne is used as the right hand operand for the assignment operator. So, the increment operator must return a Length object. We pass by reference for efficiency!

More Complications! There are a couple of other issues to consider in this case. 1. How do we differentiate between a pre- and a post-increment? 2. Should we write the operator++ function as member function or as a non-member function?

pre- or post-increment The code we just examined is for the pre-increment operator. To tell the compiler that we want the function to be for the post-increment operator, we put a dummy parameter in the function prototype, as : Length operator++ ( int ); this parameter is never actually used. It is simply a flag to the compiler that this function is overloading the post-increment operator.

Length Length::operator++ (int) { Length tl = *this; ++inches; return tl; } What’s going on here???

calling object, myLength inches5 myLength++; Length Length::operator++ (int) { Length tl = *this; ++inches; return tl; } the compiler invokes the operator++(int) function inches5 Length object tl is local to the function 6 a copy of the object tl is put on the stack and returned to the calling program. Why can’t we return a reference here?

cout << myLength++; the result is that the copy of the original object (with the original value of inches) is sent to cout. But, the inches value of myLength is equal to 6. The effect is that myLength gets incremented after (post-increment) the << operator is executed.

Member vs. Non-member When overloading ( ), [ ], ->, or any of the assignment operators, the overloading operator function must be written as a member function. For all other operators, we may write the function as a member or a non-member function. If the lefthand operand is a basic data type, or an object of a different class than the operator’s class, then the operator overloading function must be a non-member function. Non-member functions can be written as friend functions.

Friends Friend functions are non-member functions that have all of the privileges of member functions. In particular, a friend function can access private data in the class that it is a friend of.

Friendship must be given! class Length { public: Length( ); friend Length& operator++ (Length& t); private: int inches; }; the keyword friend tells the compiler that the function operator++ is a friend of the class. It is a non-member function. The function has access to the private data inches.

Length operator++ (Length& t) { t.inches++; return t; } the function goes in a.cpp file. Note that there is no scope resolution operator nor a class name because the function does not belong to the class. the code inside the function can directly access the inches data member, even though it is private. don’t include the keyword friend here. The function cannot claim it is a friend. This is done in the class definition. because it is a non-member function, we must pass the object to be worked on as a parameter.

Object Oriented purists don’t like friend functions because they break the rules of encapsulation and data hiding. If you want to be pure, provide accessor functions in the class and invoke them from the non-member function. However, this is less efficient than using a friend function.

Friend Classes A class can be a friend of another class. When a class is declared as a friend, all of its member functions can access the private data of the class it is a friend of.

Overloading Binary Operators A binary operator takes two operands. We will refer to these as the left-hand operand and the right-hand operand. a = b + c; operator left-hand operand right-hand operand

As a Member Function Length Length::operator+ (const Length& rh) { Length tLen; tLen.inches = inches + rh.inches; return tLen; } functions that overload binary operators, written as member functions, take one parameter, the right-hand operand. this value comes from the calling, or implicit object, the left-hand operand. the result of adding two Length objects ought to be a Length object.

a = b + c; operator left-hand operand right-hand operand for a, b, and c all Length objects … b. operator+ (c); The compiler generates the function invocation …

Nameless Temporary Objects In the evaluation of the expression a = b + c; the operator+ function is called to evaluate the right hand side of the equation. a Length object is returned on the stack. This object has no name, and is oftentimes called a nameless temporary object (nto). finally the assignment is done. By default, each data member of the nto is copied into the corresponding data member of the object a. after completing the assignment, the nto is removed from the stack and no longer exists.

Commutative Operators + is a commutative operator. That is, b + c; is the same as c + b;

But what if one operand is a basic data type, for example, an integer. This probably makes sense, since, for example, we can think of adding an integer, like 5, to a Length. To make the operator commutative, we should be able to write Length c = myLength +5; as well as Length c = 5 + myLength; but … how do we write the function in this case?

Rule of thumb: If the piece of data that you would normally send the message to (the left-hand operand) is a basic data type, then you have to overload the operator by writing a non-member function!

As a Non-member Function! Length operator+ ( int lh, const Length& rh) { Length tLength; tLength.inches = lh + rh.inches; return tLength; } functions that overload binary operators take two operands when written as a non- member function.

Overloading > > are binary operators where the left-hand operator is always of a different class than the one for which we are overloading the operator. For example, cout << myLength; so.. we must write these as non-member functions.

Because we want to represent a Length as feet and inches externally, we must do some conversions. As a result, the function to overload the << operator might look like: ostream &operator<< (ostream &out, const Length &rh) { int ft = rh.inches/12; int in = rh.inches %12; out << ft << “ft., “ << in << “in”; return out; } out must be passed by reference because the ostream class has no copy constructor. convert inches to feet and inches. the stream is returned so that we can cascade the << operator.

Cascading << out << ft << “ft., “ << in << “in”; this expression is evaluated first, and returns the stream out. The entire expression may now be thought of as out << “ft., “ << in << “in”; where out already contains out5

this expression is evaluated next, and returns the stream out. The entire expression may now be thought of as out << “ft., “ << in << “in”; where out already contains out5 ft. out << in << “in”;

this expression is evaluated next, and returns the stream out. The entire expression may now be thought of as out << in << “in”; where out already contains out5 ft. 3 out << “in”;

finally this expression is evaluated and returns the stream out. The return value is not used in this last instance. out << “in”; out now contains out5 ft. 3 in.

Stream Extraction Overloading the Stream Extraction operator is similar. Here, we have to decide how the user will enter in the length. In this example, I have assumed that the user will enter the number of feet, followed by white space, and then the number of inches (I would probably prompt the user to enter the data this way).

istream &operator>> (istream &input, Length &rh) { int ft, in; input >> ft; input >> in; rh.inches = in + 12 * ft; return input; }

Conversions and Overloading When converting from a basic data type to a user defined class, the compiler looks for a constructor in the class that takes the base data type as a parameter. Length::Length (const float r) { inches = r * 12; }

Now, if the programmer writes myLength = 5.3; the compiler invokes the constructor to create a nameless temporary object (nto). The assignment from the nto to the object myLength is then performed and the nto is thrown away. Note: 5.3 is in feet!

When converting from a user defined class to a base data type, the compiler looks for a function that overloads the cast operator. Length::operator float( ) { int ft, in; ft = inches/12; in = inches %12; float r = (float)in/12.0; return ft + r; } notice that no return type is declared. The return type is derived from the type of cast being done.

Now if the programmer writes float r = myLength; The compiler invokes the function written to overload the cast operator to do the conversion.

When converting from an object of one class to an object of another class, an explicit cast is not always required. A statement like orangeObject = appleObject; will cause the compiler to look for a constructor in the Orange class that takes an Apple object as a parameter, or a function in the Apple class that overloads the cast operator to return an Orange object.

If both a constructor and a cast operator are defined, the compiler will give an ambiguity error. It does not know which you want it to use.