Operator Overloading. Lecture 8. Operator Overloading. Running Example: Complex Numbers. Syntax. What can be overloaded. Syntax -- First Example



Similar documents
PART-A Questions. 2. How does an enumerated statement differ from a typedef statement?

Name: Class: Date: 9. The compiler ignores all comments they are there strictly for the convenience of anyone reading the program.

CpSc212 Goddard Notes Chapter 6. Yet More on Classes. We discuss the problems of comparing, copying, passing, outputting, and destructing

C++ Crash Kurs. C++ Object-Oriented Programming

A Summary of Operator Overloading

KITES TECHNOLOGY COURSE MODULE (C, C++, DS)

Boolean Expressions, Conditions, Loops, and Enumerations. Precedence Rules (from highest to lowest priority)

Java Interview Questions and Answers

C++ INTERVIEW QUESTIONS

More C++ Concepts. Operator overloading Friend Function This Operator Inline Function

Moving from CS 61A Scheme to CS 61B Java

CS193D Handout 06 Winter 2004 January 26, 2004 Copy Constructor and operator=

Chapter 5. Selection 5-1

Phys4051: C Lecture 2 & 3. Comment Statements. C Data Types. Functions (Review) Comment Statements Variables & Operators Branching Instructions

Schedule. Structures and Classes in C++ Outline. Goals for This Topic. Another Example of a Structure. What is a Structure? Classes May 12-17, 2005

C++FA 5.1 PRACTICE MID-TERM EXAM

Object Oriented Software Design II

Function Overloading I

AP Computer Science Java Subset

IS0020 Program Design and Software Tools Midterm, Feb 24, Instruction

Storage Classes CS 110B - Rule Storage Classes Page 18-1 \handouts\storclas

PROBLEM SOLVING SEVENTH EDITION WALTER SAVITCH UNIVERSITY OF CALIFORNIA, SAN DIEGO CONTRIBUTOR KENRICK MOCK UNIVERSITY OF ALASKA, ANCHORAGE PEARSON

13 Classes & Objects with Constructors/Destructors

Object Oriented Software Design

JAVA - QUICK GUIDE. Java SE is freely available from the link Download Java. So you download a version based on your operating system.

Calling the Function. Two Function Declarations Here is a function declared as pass by value. Why use Pass By Reference?

An Incomplete C++ Primer. University of Wyoming MA 5310

El Dorado Union High School District Educational Services

Goals for This Lecture:

The C Programming Language course syllabus associate level

Embedded Systems. Review of ANSI C Topics. A Review of ANSI C and Considerations for Embedded C Programming. Basic features of C

Sources: On the Web: Slides will be available on:

Conditions & Boolean Expressions

Subject Name: Object Oriented Programming in C++ Subject Code:

Computer Programming C++ Classes and Objects 15 th Lecture

Passing 1D arrays to functions.

Semantic Analysis: Types and Type Checking

What is a Loop? Pretest Loops in C++ Types of Loop Testing. Count-controlled loops. Loops can be...

Member Functions of the istream Class

Object-Oriented Design Lecture 4 CSU 370 Fall 2007 (Pucella) Tuesday, Sep 18, 2007

Multichoice Quetions 1. Atributes a. are listed in the second part of the class box b. its time is preceded by a colon. c. its default value is

Outline. Conditional Statements. Logical Data in C. Logical Expressions. Relational Examples. Relational Operators

Keil C51 Cross Compiler

1 bool operator==(complex a, Complex b) { 2 return a.real()==b.real() 3 && a.imag()==b.imag(); 4 } 1 bool Complex::operator==(Complex b) {

C++ Overloading, Constructors, Assignment operator

! " # $ %& %' ( ) ) *%%+, -..*/ *%%+ - 0 ) 1 2 1

Formatting Numbers with C++ Output Streams

C++ Programming Language

Introduction to C++ Introduction to C++ Week 7 Dr Alex Martin 2013 Slide 1

VB.NET Programming Fundamentals

Comp151. Definitions & Declarations

Object Oriented Software Design II

Simple C++ Programs. Engineering Problem Solving with C++, Etter/Ingber. Dev-C++ Dev-C++ Windows Friendly Exit. The C++ Programming Language

C++FA 3.1 OPTIMIZING C++

Lecture 3. Arrays. Name of array. c[0] c[1] c[2] c[3] c[4] c[5] c[6] c[7] c[8] c[9] c[10] c[11] Position number of the element within array c

C++ Outline. cout << "Enter two integers: "; int x, y; cin >> x >> y; cout << "The sum is: " << x + y << \n ;

Example of a Java program

Compiler Construction

CHAPTER 2. Logic. 1. Logic Definitions. Notation: Variables are used to represent propositions. The most common variables used are p, q, and r.

CS104: Data Structures and Object-Oriented Design (Fall 2013) October 24, 2013: Priority Queues Scribes: CS 104 Teaching Team

Statements and Control Flow

C++ program structure Variable Declarations

Chapter 2: Elements of Java

Chapter 5 Functions. Introducing Functions

Keywords are identifiers having predefined meanings in C programming language. The list of keywords used in standard C are : unsigned void

C++ Language Tutorial

Basics of I/O Streams and File I/O

Functions and Parameter Passing

Binary storage of graphs and related data

Certified PHP Developer VS-1054

Basic Programming and PC Skills: Basic Programming and PC Skills:

Basics of C++ and object orientation in OpenFOAM

UIL Computer Science for Dummies by Jake Warren and works from Mr. Fleming

Moving from C++ to VBA

For the next three questions, consider the class declaration: Member function implementations put inline to save space.

Lecture 2 Notes: Flow of Control

Chapter One Introduction to Programming

Arrays. number: Motivation. Prof. Stewart Weiss. Software Design Lecture Notes Arrays

Type Classes with Functional Dependencies

C++ Programming: From Problem Analysis to Program Design, Fifth Edition. Chapter 3: Input/Output

Common Data Structures

CS107L Handout 02 Autumn 2007 October 5, 2007 Copy Constructor and operator=

Java (12 Weeks) Introduction to Java Programming Language

Thomas Jefferson High School for Science and Technology Program of Studies Foundations of Computer Science. Unit of Study / Textbook Correlation

6.087 Lecture 2 January 12, 2010

CISC 181 Project 3 Designing Classes for Bank Accounts

C++ Input/Output: Streams

Conversion Constructors

Copyright 2001, Bill Trudell. Permission is granted to copy for the PLoP 2001 conference. All other rights reserved.

arrays C Programming Language - Arrays

Introduction to Programming (in C++) Loops. Jordi Cortadella, Ricard Gavaldà, Fernando Orejas Dept. of Computer Science, UPC

Example. Introduction to Programming (in C++) Loops. The while statement. Write the numbers 1 N. Assume the following specification:

Common Beginner C++ Programming Mistakes

Object Oriented Software Design

1 Abstract Data Types Information Hiding

Class 16: Function Parameters and Polymorphism

The C++ Language. Loops. ! Recall that a loop is another of the four basic programming language structures

Ch 7-1. Object-Oriented Programming and Classes

N3458: Simple Database Integration in C++11

Pseudo code Tutorial and Exercises Teacher s Version

Transcription:

Operator Overloading Lecture 8 Operator Overloading C++ feature that allows implementer-defined classes to specify class-specific function for operators Benefits allows classes to provide natural semantics for operators in a manner similar to built-in types Drawbacks poor use leads to confusing code many classes do not have natural overloaded semantics and, thus, overloaded operators are ambiguous it is not clear that this situation is worse than with poorly named functions however, it was serious enough that Java left the feature out Running Example: Complex Numbers Syntax Complex numbers natural class for operator overloading operators against this class are well-defined conform with user expectation thus, they are easy to use class complex public:... private: double _real; double _imag; ; Operators are treated like functions take arguments, allow implementer to define semantics Operators are invoked differently than functions unary operators (take one argument) usage: -a, *b binary operators usage: a + b, c <= d Mapping operators to functions usage: a + b matches prototypes complex & complex::operator+ ( complex & other ) Syntax -- First Example What can be overloaded operator+ -- the first example The following are equivalent note that the compiler will factor out the temporary variables I prefer the first actually (aside) don t be afraid to use temporary variables when they simplify code complex & complex::operator+ ( const complex & other ) const double real = this._real + other._real; double imag = this._imag + other._imag; return complex ( real, imag ); // Simplified complex & complex::operator+ ( const complex & other ) const return complex ( _real + other._real, _imag + other._imag ); Almost all operators Arithmetic +, -, *, /, %, ++, -- Bit-wise operators ^, &, >>, << Logical operators &&,,! Comparison >, <, <=, >=, ==,!= Array, function, comma [], (),,, ->, ->* Assignment and composite operators =, ^=, =, &=, +=, -=, *=, /=, %=, <<=, >>=, 1

What cannot be done const and Some operators cannot be overloaded Non-pointer access to class members.,.* Scope :: If/then/else operator?: New operators cannot be created, even if desired x y := x y = x ** 2 Almost all overloaded operators (except those involving equality) should be const, i.e. they should not change the implicit argument similarly, they should use const function arguments complex & complex::operator+ ( const complex & other ) const return complex ( _real + other._real, _imag + other._imag ); complex a ( 1, 2); complex b ( 2, 3); complex c = a + b; // Should not change a or b Unary and Binary Anonymous Objects and Both the unary and binary forms of an operator can be overloaded differentiated by their arguments applies to: +, -, *, & complex & complex::operator- () const return complex ( -1 * _real, -1 * imag); complex & complex::operator- ( const complex & other ) const return complex ( _real - other._real, _imag - other._imag ); First (well motivated) use of anonymous objects note it is often wrong (almost always) to modify this same reason we use const // Correct complex & complex::operator- () const return complex ( -1 * _real, -1 * _imag); // Changes this complex & complex::operator- () _real *= -1; _imag *= -1; return *this; complex a ( 1, 2); complex b = -a; // The right definition of operator- // leaves a unmodified Anonymous Objects and Polymorphic Functions and First (well motivated) use of anonymous objects note it is often wrong (almost always) to modify this same reason we use const // Correct complex & complex::operator- () const return complex ( -1 * _real, -1 * _imag); // Returns reference to stack variable complex & complex::operator- () complex c; c._real = _real * -1; c._image = _imag * -1; return c; Operator overloading is done through functions, and, thus, may be polymorphic actually, unary and binary forms are already polymorphic complex & complex::operator- ( const double a ) const return complex ( _real - a ); inumber & inumber::operator- ( inumber & other ) const return complex ( _real - other._real, _imag - other._imag ); complex a ( 1, 2); complex b = -a; // The right definition of operator- // leaves a unmodified 2

Class Arguments and Global Scope Common Overloaded Operators One argument to a operator overloaded function must be a class argument i.e. it is not possible to change the implementation of operators against built-in types Operators may also be of global scope the following are equivalent note that the second is not a class member It is preferable to have overloaded operators belong to classes. Why? Now let s construct some common operators for the complex class operator<< and operator>> operator= operator< Interestingly, all of these common cases have interesting effects that do not conform well to the operator overloading model complex & complex::operator+ ( const complex & other ) const; complex & operator+ ( const complex & other1, const complex & other2 ) const; operator>> and operator<< operator>> and operator<< So we want to print out our imaginary numbers What is the prototype of the function? Is it binary or unary? What are the arguments? xxx operator<< ( const yyy, const zzz ); xxx operator<< ( const yyy ); Two possible prototypes class scope global scope What is the problem with the first prototype? Can we make the operator a member of class complex? complex a ( 1.0, 1.0); cout << a << endl; // prints 1.0 + 1.0i ostream & ostream::operator<< ( const complex & other ); ostream & operator<< ( ostream& os, const complex & other ); Some properties of ostream operator>> and operator<< Main ostream operator ostream & ostream::operator<< ( const char [] ) Also provides for all basic types ostream & ostream::operator<< ( const type & other ); Because it returns an ostream reference, the arguments maybe chained cout << The value of PI is approximately << 3.14159 << endl; Note that the function is not constant changes the state of the ostream object Implementation of the operator must choose the operator to be global scope we cannot modify class ostream ostream & operator<< ( ostream& os, const complex & other ) 3

operator>> and operator<< operator< Implementation of the operator must choose the operator to be global scope we cannot modify class ostream How did we do? All arguments for operator<< apply to operator>> just for class istream ostream & operator<< ( ostream& os, const complex & other ) os << other._real << + << other._imag << i ; return os; An obvious operator with an (usually) obvious implementation complex numbers are not well-ordered mathematically speaking Different example -- countdown timer class CDT bool CDT::operator< ( const CDT & other ) const return ( _seconds < other.seconds ) operator< operator< The catch, when one defines operator< The compiler also creates operator> ( a < b can be used to construct b > a ) operator<= (!( a < b ) implies a <= b ) operator>= (!( b < a ) implies a >= b ) What is the danger here? The catch, when one defines operator< The compiler also creates operator> ( use a < b, but switch arguments b > a ) operator<= (!( a < b ) implies a <= b ) operator>= (!( b < a ) implies a >= b ) What is the danger here? if operator< does not provide a total ordering, then the other operators will not be well defined one good example is that of line segments operator< resolves the segment based on length any two segments of the same length will be declared equal operator= Type Conversions The C++ compiler always provides an overloaded operator= even when not requested provides a byte-wise copy of the object deep copy of built in types shallow copy of pointers Every class should provide its own operator= avoids confusing/unwanted default behavior frequently a simple function often identical to the default We will discuss shallow and deep copying tomorrow Constructors are the preferred method of converting the type of an object e.g. the following converts a double to a complex let s write it complex::complex ( double real ) _real = real; _imag = 0; complex & operator= ( const complex & other ) this._real = other._real; this._imag = other._imag; 4

Type Conversions Type Conversions Constructors are the preferred method of converting the type of an object e.g. the following converts a double to a complex how did we do? complex::complex ( double real ) : _real ( real ), _imag ( 0 ) Constructors are the preferred method of converting the type of an object Why are they the preferred technique? What is the alternative? Any constructor that accepts a single argument doubles as a type conversion routine Two circumstances under which we cannot perform type conversion via constructors they are? Two circumstances under which we cannot perform type conversion via constructors when the target type is not a class when the target type is a class that the implementer cannot modify Two circumstances under which we cannot perform type conversion via constructors when the target type is not a class when the target type is a class that the implementer cannot modify Type conversion can be performed with operators For example, if we want to construct a string out of complex Some observations we cannot do this by providing a new constructor in string this would be preferred, but we cannot change string operator string() does not have strict function semantics does not specify a return type complex::operator string () const char buffer [21]; sprintf ( buffer, %d + %di, _real, _imag ); return string ( buffer ); complex::operator string() const char buffer [21]; sprintf ( buffer, %d + %di, _real, _imag ); return string ( buffer ); 5

operator[] Questions Frequently overloaded in container classes C++ standard class vector overloads to provide array-like behavior Simple example -- look at the contents of a stack of items Rarely a good idea to overload unless the class is essentially a semantically-rich array Why can one overload the operators that access class members through pointers (->, ->*), while it is illegal to overload standard class access members (.,.*)? class stack public: item & operator[] ( int which ) const; private: vector <item> v; ; item & operator[] ( int which ) const if (( which < v.length() ) && ( which >= 0 )) return v[which]; Why/When/What to not Overload Precedence confusing precedence expected equivalence Benefit of operators is operator-like syntax, rather than functional syntax convenient, intuitive and concise,... right? but, why are there RPN calculators? Operator evaluation relies on evaluation ordering rules C++ is not the same as mathematics for example, ^ is the C++ bitwise exclusive-or (not exponentiation) overloading for exponentiation does not work a ^ 2 + 1 evaluates to a.operator^(2+1) math would prefer a.operator^(2) + 1 Functions do not have precedence problems functional notation (parentheses) ensure this Equivalence Operations Why no operator overloading in Java We have an expectation that the following are the same: a = a + 1; a++; ++a; a += 1; However, they invoke four entirely different functions It is the responsibility of the implementer to provide a complete and logically consistent set of operators frequently a tedious (and often incomplete in my experience) task Book gives a lot of guidelines on operator overloading merits and demerits dangers of usage Why would Java leave this (well-established) feature out of a very similar OO language? Do you agree with the decision? What key C++ feature relies on operator overloading? interestingly, Java is weak in this department 6

How bad does it get? How bad does it get? Frequently, for error testing, it is desirable to overload class::operator bool( ) Used to detect errors ostream::operator bool( ) returns true if an error on the stream, false otherwise However, for compatibility reasons, bool can be coerced (by the compiler) automatically to int. consider the code snippet below it would compile and attempt to shift cout x bits to the right cout << x << y << z << endl; if ( cout ) // process error cout >> x; if ( cout ) // process error // probably meant cout << x How do we solve this? Beware of Compiler Coercion Overloading class::operator void* () solves the problem void* cannot be shifted or manipulated by other operators stupid idiom to address a stupid problem If a compiler cannot find an exact match for a function prototype that you have provided, it will find a near match by coercion our example, converting bool to int This is dangerous because often it is unintended running the compiler with -Wall will let the implementer know when all such implicit coercions occur this is a very good idea cout >> x; if ( cout ) // process error // this now hurls an error as cout cannot // be coerced to a integer int x = 1; int y = -7; complex a ( x, y ); // invokes complex ( double, double ) // not so dangerous, safe-ish coercion double x = 54.2; CoundownTimer cdt ( x ); // invokes CountdownTimer ( int ) // losing the.2 seconds 7