C++ Operator Overloading

  • April 2020
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View C++ Operator Overloading as PDF for free.

More details

  • Words: 2,470
  • Pages: 24
C++ Operator Overloading

Source: How to C++ by Deitel & Deitel More notes available at: http://cplusplus-naturally.blogspot.com/

Introduction •

Operator overloading is the process of enabling existing C++’s operators to work with class objects.  Contributes to C++’s extensibility •

Examples: – << bitwise left-shift operator and stream insertion operator – >> bitwise right-shift operator and stream extraction operator – + & -  overloaded to perform differently depending on their context in integer, floating-point arithmetic and pointer arithmetic



In C++, most operators can be overloaded to be sensitive to the context in which they are used. The compiler generates the appropriate code based on the manner in which the operator is used.Compiler can distinguish between overloaded functions by looking at the data type of their arguments.



Operator overloading has clearer notion than corresponding explicit functions calls



Avoid excessive or inconsistent use of operator overloading as this can make program cryptic and difficult to program  Use when usage is obvious – similar meaning & same syntax.

Introduction – Contd… •

C++ is type-focus and type-sensitive. It is operator rich language – built-in & those defined to work with userdefined classes.



Prototype: Return type operator(parameter list) { …} type  if not ‘void’ then – Create a temp object (if object to be returned) to use as return value. – Use nameless initialized temp object (return counter(count)) – Return original object using ‘this’



To use an operator on class objects, that operator must be overloaded – with two exceptions



Operators ‘=‘ and ‘&’ can be used with any class without explicit overloading. The default behaviour of ‘=‘ is member-wise assignment and ‘&’ is used to return address of the object in memory.

Introduction Contd… •

Overloading is most appropriate for mathematical classes. These often require that a substantial set of operators be overloaded to ensure consistency with the way these mathematical classes are handled in the real world. For e.g. a complex number class must have other operators besides addition.



Choice of operator overloading depends on meaning & context of each operator.



Operator overloading functions can be – member functions, friend functions & rarely, non-member nonfriend functions



Overload operators to perform the same function or similar functions on the class objects as the operators perform on objects of built-in types.  Avoid nonintuitive use of operators



Before overloading consult the manuals for compiler restrictions & requirements unique to particular objects.

Restrictions On Operator Overloading •

Following operators cannot be overloaded: – – – –

.* :: ?: Sizeof



Attempting to overload a non-overloadable operator is syntax error.



Operator overloading cannot change operator’s: – Precedence: However, order of evaluation can be changed using paranthesis – Associativity – Arity: Operators (&,*,+,-) have unary & binary versions; thse can be overloaded separately.



It is not possible to create new operators; only existing operators can be overloaded. Attempting to do so is a syntax error. Therefore, ** can be overloaded for exponentiation.



Attempting to modify how an operator works with objects of built-in types is a syntax error.



Binary operator cannot be overloaded to be unary

Restrictions On Operator Overloading … •

Operator overloading works only with objects of userdefined types or with a mixture of an object of a userdefined type and an object of a built-in type.



Atleast one argument of an operator function must ne class object or a reference to a class object. This prevents programmers from chnaging how operators work on built-in types



Assuming that overloading an operator such as ‘+’ overloads related operators such as ‘+=‘ or that overloading ‘==‘ overloads ‘!=‘ is error. Operators can be overloaded only explicitly, there is no implicit overloading



To ensure consistency among related operators, use one to implement the others (ie use an overloaded ‘+’ operator to implement an overloaded ‘+=‘ operator).

Operator Functions as Class Members Vs Friend Functions •

Non member functions are made friends for performance reasons.



In case of binary operators, member functions use ‘this’ pointer implicitly to obtain one of their class object arguments (the left argument for binary operator)



In case of non-member functions, both class arguments must be explicitly listed in call



When overloading (), [], , or any assignment operators, the operator overloading function must be declared as class member.



For other operator, the operator overloading functions can be non-member functions



When an operator function is implemented as a member function (the leftmost (or only) operand must be a class (or a reference to a class object) of the operators’ class

Operator Functions as Class Members Vs Friend Functions … •

If the left operand must be an object of a different class or built-in type, this operator function must be implemented as a non-member function. For e.g. ‘<<‘ or ‘>>’



A non-member operator function needs to be friend if that function must access private or protected members of that class directly



If non-member functions used for operator overloading are not friend functions then set/get functions may be used. The overhead of calling these functions could cause poor performance, so these functions can be inlined to improve performance.



Operator member functions of a specific class are called only when the left operand of a binary operator is specifically an object of that class, or when the angle operand of a unary operator is an object of that class



Use non-member operator overloading function to enable the operator to be commutative. For e.g. if we overload ‘+’ as member function ten for using it with ‘long int class object Huge integer Object’, left operand must be object of that class. So, to make it commutative, overload the operator as a non-member friend function to allow HugeInteger to appear on the right of the addition.

Overloading Stream Insertion & Stream Extraction Operator •

These operators are overloaded (in class libraries provided with C++ compilers) to process each built-in data type including C-like char* string & Pointers



They can also be overloaded to perform i/o operations for user defined types



E.g. of overloading >> & << for PhoneNumber class



// Why not member function



These operators must be non-members because object of class appears in each case as the right operand must appear on the left of the operator to overload that operator as a member function.

Overloading Unary Operators •

A unary operator for a class can be overloaded as a non-static member function with no arguments or as a non-member function with one argument; that argument must be either an object of the class or a reference to an object of the class.



Non-static so that they can access non-static data members because static member functions can only access static data members of the class



E.g. overloading ! Operator for class string to check if empty & return a bool result



Case 1: Non-static member function with no arguments – !s is converted into s.operator!() is invoked Class string { public: bool operator !() const; …. }; – Operator is used on the object of which it is a member

Overloading Unary Operators … •

Case 2:Non-member function with one argument (Object copy / Object reference) !s  operator!(s) class string{ friend bool operator(const string &) … };



When overloading unary operator it is preferable to make the operator function class member instead of non-member friend function.



Friend function and friend classes must be avoided unless they are absolutely necessary. The friend usage violates the use of encapsulation of a class.

Overloading Binary Operators •

The argument on the LHS of operator is the object of which operator is a member function. The object on the RHS must be furnished as an argument to operator. Returned value may be assigned or used in any other ways.  Overloaded operator always require on less argument than its number of operands.



Overloading as non-static member function with one argument y+=z operator+=(z) const string &operator +=(const string &);



Non-member function with two arguments (one of them needs to be either a class object or a reference to a class object) y+=z operator+=(y, z) friend const string &operator +=(string &, const string &);

Case Study: An Array Class •

Arrays in C++ just an alternative to pointers  so, arrays have much potential for errors.



For arrays, C++ does not provide such capabilities like – Subscript range checking – Two arrays comparison with equality/relational operators – When an array is passed to a general purpose function designed to handle arrays of any size, the size of the array must be passed as an additional argument. – One array cannot be assigned to another with assignment operator (s) (because array names are const pointers & a const pointer cannot be used on LHS of assignment operator.



But C++ does provide means to implement these capabilities through the mechanisms of operator overloading.



//array example



Subscript operator [] can be used to select elements from container classes like linked lists, strings, dictionaries etc. Also, subscripts no longer have to be integer; they can be characters, strings, floats or even objects of user-defined classes

Case Study: An Array Class … •

Copy constructor must use call-by-reference not callby-value. Otherwise, the copy constructor call results in infinite recursion (a fatal logical error) because for callby-value a copy of the object passed to the copy constructor must be made, which results in copy constructor being called recursively. A copy constructor is used to initialize an object with another object of same class…(to be completed from chapter highlights)



If the copy constructor simply copied the pointer in the source object to the target object’s pointer, then both objects would point to the same dynamically allocated storage. The first destructor to execute would then delete the dynamically allocated storage & the other object’s pointer would then be undefined, a situation called a “dangling pointer” & likely to result in serious run-time error.



A constructor, a destructor, an overloaded assignment operator and a copy constructor usually provided as a group of any class that uses dynamically allocated memory. Not providing an overloaded assignment operator and a copy constructor for such a class is a syntax error.

Case Study: An Array Class … •

Declaring assignment operator as private prevents one class object being assigned to another.



Making overloaded assignment operator & copy constructor private prevents class objects from being copied



Self assignment of objects is dangerous because …



Multiple Overloading: If in same program with multiple classes having same operator being overloaded then C++ can select correct function to carry out “addition” based on type of operand.

Converting between Types •

Conversion is required in assignments, in calculations, in passing values to functions & in returning values from functions.



Compilers know how to perform certain conversions among built-in types. This implicit conversion is done through built-in routines. Can also convert if userdefined objects are same on both sides.



For conversion among user-defined types & built-in types, conversion constructors are needed – single argument constructor that turn objects of other types (including built-in types) into objects of a particular (constructor’s) class. This constructor is called implicitly by the constructor.



A constructor/cast operator converts an object of one class into an object of another class or into an object of a built-in type. //Assignment operator or overloaded role from CHHG



This operator must be a non-static member function



It cannot be a friend function



It does not specify a return type – type to which an object is being converted



Prototype for cast operator: CastFromClass::operator const

Converting between Types … •

Prototype for cast operator: CastFromClass::operator const – E.g. A::operator char *() const; (char *)s=s.operator char*()



When necessary, the compiler can call cast operators and conversion constructors to create temporary objects – E.g. for object ‘s’ of class string, cout << s is converted by compiler to first (char *) as required by cout  so for class string << need not be overloaded for cout



For converting a basic type into user-defined type, one argument constructor is used. Complier blurs distinction between definition & assignment. If no overloaded operator available then compiler will look for the constructor to do the same job. Distance d1 = 2.345; d1 = 1.0;  Constructor is used but no new object is created (through unnamed object) For converting a user-defined type to basic, a conversion function is required – Mtrs=float(dist2) and mtrs = dist2 will use same conversion function





Converting between Types … •



For converting from user-define to another user-defined type then if conversion routine to be in source object, use conversion function else (conversion routine to be in destination object) use one-argument constructor. In second case, special functions (get functions) may be required to provide access to private data members of object to be converted

 Avoid doing same conversion in more than one way i.e. single argument constructor is destination object & conversion function in source object.

Overloading ++ and -•

These operators have both prefix and postfix versions.



So, each operator overloading function must have a distinct signature so the compiler will be able to determine which versions of ++/-- is intended



Prefix versions are overloaded exactly as any other prefix unary operator would be.



Postfix versions are overloaded in a manner to have different signature, achieved by making argument list for postfix version.



Example declarations: Date d1; Pre-incrementing Member function: ++d1 = d1.operator(); Prototype Date operator ++() Non-member function: ++d1 = operator(d1); Prototypefriend Date operator++(Date &) Post-incrementing Member function: d1++ = d1.operator(0); Prototype Date operator ++(int) Non-member function: d1 ++= d1.operator(d1,0); Prototypefriend Date operator++(Date &,int)

Overloading ++ and -- … •

Similar is the case for pre-and post decrementing

 It is not an argument but a signal to compiler to use postfix notation. c2 = c1++;  c1 is first assigned to c2 and then incremented

Operators that cannot be overloaded • • • • •

Member access dot operator (.) Scope resolution (::) Conditional Operator (?:) Pointer to member (.*) sizeof()

Some uses of operator overlaoding • • • • •

Add English distances: Add X1 to X2 & Y1 to Y2 Add Polar Co-ordinates: 3 step approach  convert to English, Add, Convert back String Concatenation: Check final string should not result in overflow Distance & String comparison Polar to rectangular conversion

More notes available at:

• http://www.cplusplus-naturally.blog

• http://zainvi.sf.googlepages.com/in

• http://www.computer-science-note

k n a

h T

 u

o Y

? s n o i ? t s s n e o u i t Q s e g g Su

Related Documents

C++ Operator Overloading
April 2020 13
Operator C++
July 2020 15
Operator
May 2020 27
Method Overloading
November 2019 9