Learning Objectives • • • • Fundamentals of Operator Overloading. Restrictions of Operator Overloading. Global and member Operator. Overloading Stream-Insertion and Stream-Extraction Operators. • Overloading Unary Operators. • Overloading Binary Operators. Operating overloading • • • • • C++ enables the programmer to overload most operators to be sensitive to the context in which they are used. The compiler generates an appropriate function or method call based on the operator's use. To overload an operator, write a function definition; the function name must be the keyword operator followed by the symbol for the operator being overloaded. To use an operator on class objects, that operator must be overloaded - with two exceptions. The assignment operator (=) may be used with two objects of the same class to perform a default memberwise assignment without overloading. The address operator (&) also can be used with objects of any class without overloading; it returns the address of the object in memory. The point of operator overloading is to provide the same concise expressive power for user-defined data types that C++ provides with its rich collection of operators that work on built-in types. Operator overloading is not automatic - the programmer must write operator overloading functions to perform the desired operations. Sometimes these functions are best made methods; sometimes they are best as friend functions. Restrictions on Operator Overloading + - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- ->* , -> [] () new delete new[] delete[] Fundamentals of Operator Overloading • Process that enables C++’s operators to work with class objects. • C++ has ability to provide the operators with a special meaning for a data. The mechanism of giving such special meanings to an operator is known as operator overloading. • C++ can overload the entire C++ operator except following: 1. Class member access operator (. ) 2. Scope resolution operator (::) 3. Size operator (sizeof) 4. Conditional operator (? :) Why do we need operator overloading? Do we really need it? • For instance, compare the following syntaxes to perform addition of two objects a and b of a user-defined class Fraction (assume class Fraction has a member function called add() which adds two Fraction objects): c = a.add (b); c = a+b; • After overloading the appropriate operators, you can use objects in expressions in just the same way that you use C++'s built-in data types. • If you use the operator without providing the mechanism of how these operators are going to perform with the objects of our class, you will get error message Fundamentals of Operator Overloading • Process that enables C++’s operators to work with class objects. • C++ has ability to provide the operators with a special meaning for a data. The mechanism of giving such special meanings to an operator is known as operator overloading. • C++ can overload the entire C++ operator except following: 1. Class member access operator (. ) 2. Scope resolution operator (::) 3. Size operator (sizeof) 4. Conditional operator (? :) Why do we need operator overloading? Do we really need it? • For instance, compare the following syntaxes to perform addition of two objects a and b of a user-defined class Fraction (assume class Fraction has a member function called add() which adds two Fraction objects): c = a.add (b); c = a+b; • After overloading the appropriate operators, you can use objects in expressions in just the same way that you use C++'s built-in data types. • If you use the operator without providing the mechanism of how these operators are going to perform with the objects of our class, you will get error message Defining operator overloading • operator function : Defines the operations that the overloaded operator will perform relative to the class upon which it will work. An operator function is created using the keyword operator. • Operator functions can be either members or nonmembers of a class. Nonmember operator functions are almost always friend functions of the class. • The way operator functions are written differs between member and nonmember functions. • The general format of member operator function is: return type class name :: operator op(arglist) { function body // task defined } Example: #include <iostream> using namespace std; class Overload { public: int num; Overload() {num=0; } void operator*(); }; void Overload::operator*( ) { num*=num; cout<<"\n Num ="<<num; num+=1; } int main( ) { OUTPUT: Overload obj; Num =0 *obj; Num =1 *obj; -------------------------------return 0; Process exited after 0.01693 seconds with return value 0 Press any key to continue . . . } #include<iostream> using namespace std; class xyz{ int x, y, z; public: void get(){ cout<<"XYZ please\n"; cin>>x>>y>>z; } void disp(){ cout<<x<<y<<z<<endl; } friend void operator-(xyz &S);//pass by reference }; void operator-(xyz &S){ S.x=-S.x;//object name must be used as it is a friend function S.y=-S.y; S.z=-S.z; } int main(){ xyz s1; s1.get(); OUTPUT: cout<<"BEFORE OVERLOADING\n"; XYZ please s1.disp(); 456 cout<<"AFTER OVERLOADING \n"; BEFORE OVERLOADING -s1; 456 s1.disp(); AFTER OVERLOADING return 0; -4-5-6 } -------------------------------Process exited after 4.041 seconds with return value 0 Press any key to continue . . . Overloading Stream-Insertion and Stream-Extraction Operators • Overloaded << and >> operators – Overloaded to perform input/output for user-defined types – Left operand of types ostream & and istream & – Must be a non-member function because left operand is not an object of the class – Must be a friend function to access private data members Example: #include <iostream> using namespace std; class Distance { private: int feet; // 0 to infinite int inches; // 0 to 12 public: // required constructors Distance(){ feet = 0; inches = 0; } Distance(int f, int i){ feet = f; inches = i; } friend ostream &operator<<( ostream &output, const Distance &D ) { output << "F : " << D.feet << " I : " << D.inches; return output; } friend istream &operator>>( istream &input, Distance &D ) { input >> D.feet >> D.inches; return input; } }; int main() { OUTPUT: Distance D1(11, 10), D2(5, 11), D3; Enter the value of object : cout << "Enter the value of object : " << endl; 45 6 First Distance : F : 11 I : 10 cin >> D3; Second Distance :F : 5 I : 11 cout << "First Distance : " << D1 << endl; Third Distance :F : 45 I : 6 cout << "Second Distance :" << D2 << endl; cout << "Third Distance :" << D3 << endl; -------------------------------return 0; Process exited after 5.81 seconds with return value 0 Press any key to continue . . . } Cont… • Operators that cannot be overloaded • . .* :: ?: • It is not possible to change the “arity” of an operator ie. The numbers of operands an operator takes. • Overloaded unary operators remain unary operators and overloaded binary operators remain binary operators. Cont… • Operator overloading is not automatic • Must write operator-overloading functions to perform the desired operations • Call on an object of the class and operate on that object • To use an operator on an object of a class, must define overloaded operator functions for that class • 1. The assignment operator(=) may be used with most classes to perform memberwise assignment of the data members – each data member is assigned from the assignment’s “source”(on the right) object to the “target” object (on the left). • Memberwise assignment is dangerous for classes with pointer members, so well’l explicitly overload the assignment operator for such classes • The address (&) operator returns a pointer to the object; this operator also can be overloaded Cont… • The comma operator evaluates the expression to its left then the expression to its right , and returns the value of the latter expression. • This operator also can be overloaded. • The ability to provide the operators with a special meaning for a data type and this mechanism of giving such special meanings to an operator is known as operator overloading. Cont… • Syntax: • Returntype classname::operator op(arg-list) • { Functionbody // task defined } Where returntype is the type of value returned by the specified operation and op is the operator being overloaded. The op is preceded by the keyword operator. Operator op is the function name. Cont… • The process of overloading involves the following steps: • 1. First, create a class that defines the datatype that is to be used in the overloading operation. • 2.Declare the operator function operator op() in the public part of the class. It may be either a member function or a friend function. • 3.Define the operator function to implement the required operations. Overloading stream insertion and a stream extraction operators • Fundamental types using the stream extraction operator>> • Stream insertion operator<< • The class libraries provide with c++ compilers overload these operators to process each fundamental type, including pointers and C- like char * strings. • The stream insertion and stream extraction operators also can be overloaded to perform input and output for user-defined types. Cont… • • • • • • • • Example: #ifndef PHONE NUMBER_H #define PHONE NUMBER_H #include <iostream> Using std::ostream; Using std::istream; #include<string> Using std:: string; Cont… • Class phonenumber • { • Friend ostream &operator<<(ostream &, const phonenumber &); • Friend istream &operator>>(istream&, phone number &); • Private: • string areacode; • string exchange; Cont… • • • • • • • • • String line; }; *endif # phonenumber.cpp #overloaded stream insertion and stream extraction operators # for class phonenumber #include<iomanip> Using std::setw; #include “phonenumber.h” Cont… • • • • //overloaded stream insertion operator; cannot be //a member function if we would like to invoke it with // cout << some phonnumber; Ostream &operator<<(ostream &output, const phonenumber &number) • { output<<“(“ <<number.areacode<<“)” << number.exchange<<“_” <<number.line; return output; } Cin>> some phonnumber Istream &operator >> (istream &input, phonenumber &number) Cont… • { input.ignore(); input>>setw (3)>> number.areacode; input.ignore(2); input>>setw (3)>>number.exchange; input>>ignore(); input>>setw (4)>> number.line; Return input; }// end function operator>> Cont… • • • • • • • • • • • • • • • • #include <iostream> Using std :: cout; Using std :: cin; Using std :: endl; # include “phonenumber.h” Int main() { Phonenumber phone; Cout<<“enter phone number in the form (123) 456-7890:”<<endl; Cin >>phone; Cout<<“The phone entered was:”; Cout<<phone invokes operator<< by implicitly issuing Cout<<phone<<endl; Return 0; } //end main Cont… • Output: • Enter phone number in the form (123) 4567890: • (800) 555-1212 • The phone number entered was:(800) 5551212 Cont… • • • • • • • • Unary operators Op x or x Op Binary operators X op y Friend functions Operator op (x) Member functions Operator op (x.y) Global and member operators • Operators that are loaded as member functions • (),[], -> any other assignment operators, the operator overloading function must be declared as a class member. • For other operators, the operator overloading functions can be class members or global functions. Cont… • Operators as member functions and global functions • When an operator function is implemented as a member function, the leftmost operand must be an object(or a reference to an object) of the operator’s class. Overloading stream-insertion and stream –extraction operators • The overloaded stream insertion operator(<<) is used in an expression in which the left operand has type ostream &, as in cout<< class object. • To use the operator, the right operand is an object of a user –defined class, it must be overloaded as a global function. • For a member function operator << have to be a member of the ostream class. • Istream &,as in cin>> class object and the right operand is an abject of a user-defined class – it must be a global function. Cont… • Is able to input and output the fundamental types using the stream extraction operator>> and the stream insertion operator<<. • The class libraries provided with compiler overload these operators to process each fundamental type, including pointers and strings • The stream insertion and stream extraction operators also can be overloaded to perform input and output for user defined types. Cont… • • • • • • • • • • • • Example: # include (iostream> # include<string> Class phonenumber { friend ostream &operator<<(ostream &,const phonenumber &); friend istream &operator>>(istream &, phonenumber & ); Private: string areacode; string exchange; string line; }; • #endif Overloading unary operators • A unary operator for a class can be overloaded as a non static member function with no arguments or as a global function with one argument • That argument must be either an object of the class or a reference to an object of the class. • Example: • Class string • { • Public: bool operator!() const; ….. }; Overloading binary operators • A binary operator can be overloaded as a non – static member function with one argument or as a global function with two arguments(one of those arguments must be either a class object or a reference to a class object). • Class string • Public: bool operator<(const stsring &)const; … }; Cont… • • • • Example: unary operator # include <iostream.h> Class space { Int x; Int y; Int z; Public: Void getdata(int a, int b, int c); Void display (void); Void operator-(); // overload unary minus }; Void space :: getdata(int a, int b, int c) { x = a; y = b; z = c; } Cont… • • Void space :: display (void) { cout << x<<“”; cout<< y <<“”; cout<< z<< “\n”; } Void space :: operator-() //defining operator-() { X = -x; Y = -y; Z = -z; } Main() { space s; s.getdata(10, -20, 30); cout << “s : “; s.display(); -s; //activates operator –() Cout<<“S : “ ; S.Display (); } Output: S : 10 -20 30 S : -10 20 -30 Cont… • • • • • • • • • • • • • • • • Example : Over loading Binary operators: # include <iostream.h> Class complex { float x; //real part float y; // Imaginary part Public: complex () complex(float real, float imag} [ x= real; y=imag;] complex operator+(complex); void display (void); }; Complex complex :: operator + (complex c) { Complex temp; //temporary temp.x = x + c.x; //float addition temp.y = y + c.y; //float addition return (temp); Cont… • • Void complex :: display (void) { cout<<x<< “ + j” <<y<<“\n”; } Main() { complex C1,C2,C3; C1 = complex (2.5, 3.5); C2 = complex (1.6, 2.7); C3 = C1 + C2; cout << “ C1 = “ ; C1.display(); cout<< “ C2 = “ ; C2.display(); cout<< “ C3 = “; C3. display(); } Output C1 = 2.5 + j3.5 C2 = 1.6 + j2.7 C3 = 4.1 + j6.2