Download
operator overloding n.
Skip this Video
Loading SlideShow in 5 Seconds..
OPERATOR OVERLODING PowerPoint Presentation
Download Presentation
OPERATOR OVERLODING

OPERATOR OVERLODING

215 Views Download Presentation
Download Presentation

OPERATOR OVERLODING

- - - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

  1. OPERATOR OVERLODING

  2. Objectives • Operator Overloading • Type Conversion • New Style Casts and • RTTI(Run time type Information)

  3. Overloading an operator means programming an operator to work on operands of types it has not yet been designed to operate. Overloading Operators—The Syntax: • Operators are overloaded by writing operator-overloading functions. • These functions are either member functions or friend functions of that class whose objects are intended as operands of the overloaded operator. • Operator overloading functions are very similar to the member functions and friend functions. The only thing peculiar about them is their name. • The names of operator-overloading functions are composed of the keyword operator followed by the symbol of the operator being overloaded. • We can overload all the C++ operators except the following: (i) class member access operator(., .*) (ii) scope resolution operator (::) (iii) size operator (sizeof) (iv) conditional operator(?:)

  4. Overloading Operators—The Syntax: • The syntax for member functions that overload a given operator is as follows: • Member functions that overload operators can be private, protected, or public. • The prototype of the operator-overloading function specifies a return type. • The keyword operator follows the return type. • This is followed by the symbol of the operator being overloaded. • Finally, a pair of parentheses containing the formal arguments is specified.

  5. Overloading Operators—The Syntax: • The syntax for a friend function that overloads a given operator is as follows: • Operator-overloading function can be defined and used as a member function. (See Example 1) • Operator-overloading function can be defined as a friend function. (See Example 2).

  6. Overloading Operators—The Syntax: Defining operator overloading using member function Example1: class <class name> { <return type> operator <op> (<argumentlist>); //prototype }; <return type> <classname> ::operator <op> (<argumentlist>)//definition { //Function body } • Where returntype is the type of value returned by the specified operation. • operator op is the function name. • Operator functions must be either member functions or friend functions.

  7. Overloading Operators—The Syntax: Defining operator overloading using friend function Example2: class <class name> { friend <return type> operator <op> (<argumentlist>); //prototype }; return type operator <op> (<argumentlist>)//definition { //Function body } • Where returntype is the type of value returned by the specified operation. • operator op is the function name.

  8. Differences between member function and friend function w.r.to operator overloading • A basic difference between them is that a friend function will have only one argument for unary operators and two for binary operators, while a member function has no arguments for unary operators and only one for binary operators. • The friend function takes one argument more than member function because the invoking object appears as an explicit parameter to the friend function whereas in member functions it is passed as an implicit parameter.

  9. The process of operator overloading involves the following steps: • Create a class that defines the data type to be used in the overloading. • Declare the operator function operator op() in the public part of the class. It may be either a member function or a friend function. • Define the operator function to implement the required operations. • Overloaded operator functions can be invoked by expressions such as: op x or x op : for unary operator x op y : for binary operators

  10. Overloading unary minus

  11. void space :: getdata(int a, int b, int c) { x=a;y=b;z=c; } void space ::display(void) cout<<x; cout<<y; cout<<z; } void space:: operator-() { x=-x; y=-y; z=-z; }

  12. int main() { space S; S.getdata(10,-20,30); cout<<"S:"; S.display(); -S; cout<<"S"; S.display(); return 0; } output 10 -20 30 -10 20 -30

  13. To overload unary minus using friend function friend void operator-(space &s); // declaration void operator -(space &s) // definition { s.x=-s.x; s.y=-s.y; s.z=-s.z; }

  14. overloading binary operators to add two complex numbers c=sum(A,B) // functional notation c=A+B // arithmetic notation overloading + operator to add two complex numbers: class complex { float x;//real part float y;//imaginary part public: complex(){};// constructor 1

  15. complex (float real, float imag) //constructor 2 { x=real;y=imag; } complex operator+(complex); void display(void); };

  16. complex complex::operator+(complex c) { complex temp; temp.x=x+c.x; temp.y=y+c.y; return(temp); } void complex::display(void) { cout<<x<<"+j"<<y<<"\n"; }

  17. int 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(); return 0; }

  18. C1=2.5+i3.5; C2=1.6+i2.7; C3=4.1+i6.2; The operator+() operates in the following way: • it receives only one complex argument explicitly • it returns a complex type value • it is a member function of complex C3=C1+C2; // invokes operator+() function • C1 takes the responsibility of invoking function. • C2 is the argument object The statement is equivalent to C3=C1.operator+(C2);// usual function call temp.x=x+c.x; c.x refers to object C2 and x refers to object C1, since data members of C1 are accessed directly.

  19. OVERLOADING BINARY OPERATOR USING FRIENDS The complex number program can be modified as follows: 1.Replace the member function declaration by the friend function declaration friend complex operator+(complex, complex); 2.Redifine the operator function as follows complex operator+(complex a, complex b) { complex temp; temp.x=a.x+b.x; temp.y=a.y+b.y; return(temp); }

  20. in this case the statement C3=C1+C2 is equivalent to C3=operator+(C1,C2); Reason for using overloading using friend function: Suppose A and B are the objects of the same class then, A=B+2; // will work for the member function &friend function A=2+B; //will not work for member function , but will work for //friend function, since left-hand operand is responsible for invoking the member function.

  21. Compiler Interpretation of Operator-Overloading Functions • The compiler interprets operator-overloading functions is shown : • s3=s1+s2; // s1,s2 and s3 are objects of the class string • If the operator overloading function has been declared as a member function, then the following interpretation is satisfied: • s3=s1.operator+(s2); • If the operator overloading function has been declared as a friend function, then the following interpretation is satisfied: • s3=operator+(s1, s2); • However, we must note that the operator-overloading functions can be called directly from within the application programs : • s3=s1.operator+(s2); • s3=operator+(s1, s2); • The benefit of overloading the operator will not be felt if the overloaded operators are directly called in this manner.

  22. Manipulating string using operators • There are no operators for manipulating the strings. • In order to copy one string to another , the programmer must first determine its length and allocate the required amount of memory. • C++ allows us to create our own definitions of operators that can be used to manipulate the strings very much similar to the decimal numbers. • We can manipulate the strings using string class as follows: • For example , we shall able to use statements like: string3 = string1 + string2

  23. Example illustrating the applications of overloaded operators #include <iostream.h> #include <string.h> class string { char *p; int len; public: string () { len = 0; p=0; } //create null string string (char *s) { len=strlen(s); p=new char[len+1]; strcpy(p,s); }

  24. friend string operator + (string &s, string &t); friend string void show(string s); }; string operator + (string &s , string &t) { string temp; temp.len=s.len+t.len; temp.p=new char[temp.len+1]; strcpy(temp.p,s.p); strcat(temp.p,t.p); return (temp); }

  25. void show (string s) { cout<<s.p<<endl;} void main() { string s1 = "New"; // string s1(“New”); string s2 = "Delhi"; string s3; clrscr(); s3=s1+s2; show(s1); show(s2); show(s3); getch(); }

  26. Operator overloading becomes mandatory under the following circumstances: 1. Objects of the class acquire resources dynamically during run time and no two objects should share the same copy of the resource. Example: string s1(“abc”), s2; s2=s1; 2. Objects of the class acquire some resources dynamically during run time and no two objects should share even different copies of the resource. Example: s2=s1; // should not compile at all The solution is to declare the function to overload the assignment operator in the private section of the class. This will produce an compile time error. 3. Objects need to be passed as parameters in function templates and the operators being used on template class objects within the template functions should work in the same way on objects of the class. 4. Change in the implementation of the class forces an undesirable change in its interface in turn necessitating the rewriting and recompiling of the application programs.

  27. Operator overloading becomes mandatory under the following circumstances: 5. The default action of the dynamic memory management operators (new and delete) are unsuitable for the class being designed. • By default, the new operator allocates the amount of memory requested, and also stores the amount of memory allocated in the memory itself. • In memory critical applications, overloading the new operator can prevent a huge wastage of memory. • By default, the new operator simply allocates memory for the object whose type is passed as an operand to it. To prevent the class from having more than one object, subsequent calls to the new operator should not create more objects, but merely return the address of the object that was created in response to the first call to the new operator. 6. Overloading provides better readability of code.

  28. Rules for Operator Overloading • New operators cannot be created: New operators (such as **) cannot be created. • Example: • class A • { • public: void operator **(); //illegal attempt to create a new operator • }; • 2. Meaning of existing operators cannot be changed: • Any operator-overloading function (member or friend) should take at least one operand of the class of which it is a member or friend. Thus, it is not possible to change the manner in which an existing operator works on operands of fundamental types (char,int, float, double). • Example: • class A • { public: friend int operator + (int, int); //illegal attempt to modify the behavior of operators • }; • In case of member functions, this condition is automatically enforced because the address of the calling object is implicitly passed as a parameter to it. • However, in case of friend functions, the library programmer needs to take extra care. By ensuring that at least one operand of an operator-overloading function must be of the class type, the compiler ensures that the meanings of the existing operators cannot be changed.

  29. Rules for Operator Overloading Some of the existing operators cannot be overloaded: The following operators cannot be overloaded: :: (scope resolution) . (member selection) .* (member selection through pointer to member) ?: (conditional operator) sizeof (finding the size of values and types) typeid (finding the type of object pointed at) Some operators can be overloaded using non-static member functions only: = (Assignment operator) () (Function operator) [] (Subscripting operator) -> (Pointer-to-member access operator) These operators cannot be overloaded using friend or static functions

  30. Rules for Operator Overloading Number of arguments that an existing operator takes cannot be changed: Operator overloading functions should take the same number of parameters that the operator being overloaded ordinarily takes. For example, the division operator takes two arguments. Example: class A { public: void operator / (); //illegal attempt to modify the no. of arguments }; 6. Overloaded operators cannot take default arguments: An illegal attempt to assign a default value to an argument of an operator-overloading function causes a compile-time error. Example: class A { public: void operator / (int =0); //illegal attempt to assign a default value to opeartor overloaded function };

  31. Rules for Operator Overloading 7. It is highly imprudent to modify the values of the operands that are passed to the operator-overloading functions. Example: class string { char *cstr; long intlen; public: string operator + (string &); }; string string :: operator + (string &ss) { this -> cstr=NULL; //BUG: left-hand parameter changed // rest of the function ss.cstr->=NULL ; //BUG } To guard against this mishap, the operator-overloading function can be declared.

  32. Rules for Operator Overloading To guard against this mishap, the operator-overloading function can be declared: class string { char *cstr; long intlen; public: string operator + (const string &) const; };

  33. Overloading Various Operators • Overloading increment and decrement operators (prefix and postfix): The prototype and definition of the operator-overloading function for the class Distance is shown in the example: • The operator-overloading function should be public because it will mostly be called from within functions that are not members of the class Distance. • It should not be a constant member function since it will certainly modify the value of at least one of the data members of the calling object. • First, the increment operator works (since it is in prefix notation). • The explicit call to the constructor creates a nameless object of the class distance by passing the incremented value of feet and the unaltered value of inch as parameters. • The operator-overloading function returns the nameless object thus constructed.

  34. Overloading Various Operators Example: Overloading increment operator for distance class in prefix notation class distance { int feet; float inch; public: distance () { feet=inch=0;} distance (int x, float y) { feet=x; inch=y;} // rest of the class distance operator ++(); }; distance distance:: operator ++ () { return distance(++feet, inch); } • If d1 and d2 are the 2 objects of the class distance , then the statement: d2=++d1; Is interpreted by the compiler as: d2=d1.operator++();

  35. Overloading Various Operators • If the call to the operator-overloading function is on the right-hand side of the assignment operator, the values of the returned object will expectedly be copied to the object on the left. • An additional operator-overloading function to overload the increment operator can be defined in postfix notation. Example: Overloading increment operator for distance class in postfix notation class distance { public: // rest of the class distance operator ++(int); }; distance distance:: operator ++ (int) { return distance(feet++, inch); }

  36. Overloading Various Operators • The constructor gets called before the increment operator executes because the increment operator has been purposefully placed in postfix notation. Thus, a nameless object with the initial values of the calling object is created. • The increment operator increments the value of feet data member of the calling object. Finally, the nameless object constructed earlier with the initial values of the calling object is returned. • If the call to this operator-overloading function is on the right-hand side of the assignment operator and there is an object of the class distance on its left, then the object on the left will get the initial values of the object on the right. The value of the object on the right will alone be incremented. • These two operator-overloading functions convincingly duplicate the default action of the increment operator on intrinsic types.

  37. Overloading Various Operators • If we provide an operator-overloading function for the increment operator in prefix notation, we must provide one for the postfix notation also. • Decrement operators are overloaded in the same way as the increment operators. • If d1 and d2 are the 2 objects of the class distance , then the statement: d2=d1++; Is interpreted by the compiler as: d2=d1.operator++ (0); //integer 0 • If the compiler finds a exact matching prototype for postfix form, it compiles without warning errors. • However, if it finds prototype for prefix form only it gives warning but still compiles with distance::operator+(). i.e., the compiler first looks for a function with an integer as a formal parameter.

  38. Overloading Various Operators Overloading unary minus and unary plus operator: The unary minus operator can be overloaded through a member function. (The operator can be overloaded by a friend function also.) Example: class A { int x; public: A(int=0); A operator –(); // or friend A operator –( A &) }; A A::operator-() // A operator – (A &Aobj) { return A(-x); // or return A (-Aobj.x) ; }

  39. Overloading Various Operators • Overloading arithmetic operators: • The syntax for overloading the arithmetic operators through member functions is as shown: • <return type> operator <arithmetic symbol> (<parameter list>); • An object that will store the value of the right-hand side operand of the arithmetic operator will appear in the list of formal arguments. • The left-hand side operand will be passed implicitly to the function since the operator-overloading function will be called with respect to it. • 2. The syntax for overloading the arithmetic operators through friend functions is as shown: • friend <return type> operator <arithmetic symbol> (<parameter list>); • Objects that store the values of the left-hand side and the right-hand side operands of the arithmetic operator will appear in the list of formal arguments.

  40. Overloading Various Operators • Overloading arithmetic operators: • How to overload the addition operator for the class Distance is as shown : • distance d1(7,8), d2(4,9),d3; • d3=d1+d2; • This can also be done through either by member function or by friend function. • This code works fine if the right-hand side operand of the addition operator is an object of class Distance. • However, if it is a float-type value, then the preceding function will not work. • Example: • d3=d1+9.5; //will not work • Because, the compiler will interpret this statement as: • d3= d1.operator+(9.5);

  41. Overloading Various Operators • Overloading arithmetic operators: • However, introducing a suitable constructor that converts from float to Distance solves the problem. • class distance • { public: • distance (float ); • distance operator +(distance); • }; • distance:: distance( float p) • { • feet= (int) p; • inch=(p-feet)*12; • } • However,if the left-hand side operand is of float type, the member function given in Listing 8.20 is replaced with a friend function. (See Listing 8.22).

  42. Overloading Various Operators • Overloading arithmetic operators: • However,if the left-hand side operand is of float type, for example: • d3=9.5+d1; //will not work for member function • Because, the compiler will interpret this statement as: • d3= 9.5.operator+(d1);//illegal • the member function given in previous example is replaced with a friend function. • class distance • { public: • distance (float ); • friend distance operator +(distance, distance); • }; • distance:: distance( float p) • { • feet= (int) p; • inch=(p-feet)*12; • }

  43. Overloading Various Operators • The friend function given in previous example tackles all three conditions as follows: • Both the left-hand side and the right-hand side operands are objects of class Distance: The operator-overloading function is called straight away without any prior conversions. • The right-hand side operand is a float-type value while the left-hand side operand is an object of class Distance: The right-hand side operand is first converted into an object of the class Distance by the constructor and then the operator-overloading function is called. • The left-hand side operand is a float-type value while the right-hand side operand is an object of class Distance: The left-hand side operand is first converted into an object of the class Distance by the constructor and then the operator-overloading function is called.

  44. Overloading Various Operators • Where both operands are float-type values, the operator-overloading mechanism will not be invoked at all. Instead, the float-type values will simply get added to each other. • For the class Distance, there is no function that converts a float-type value to an object of class Distance. The constructor that takes a float-type value as a parameter and initializes the object with it will be called. This is despite the fact that the object is being created and initialized by two separate statements. Such a constructor is called an implicit constructor. • Having both a friend function and a member function will lead to ambiguity errors.

  45. Overloading Various Operators • Overloading assignment operator: • The assignment operator is a binary operator. If overloaded, it must be overloaded by a non-static member function only. Thus, the syntax for overloading the assignment operator is as shown : • class_name & operator = (class_name &); • By default, the compiler generates the function to overload the assignment operator if the class designer does not provide one. This default function carries out a simple member-wise copy. For example: • Example: • class A • { • public: • &A operator = (A&); • }; • A & A::operator =(A & rhs) • { *this=rhs; • return *this; • } • In most cases, this default assignment operator is sufficient. However, there are cases where this default behaviour causes problems if the copy constructor is not defined. (See Listing 8.30). Pg 236 further explanation required

  46. In most cases, the default assignment operator is sufficient. For classes that acquire resources dynamically, default causes problem. • String s1(“abcd”); String s2= s1; • The conclusion is that the assignment operator must be defined for a class whom the copy constructor is defined. Example String (const String &); // copy constructor String & operator = (const String &); String String :: operator = (const String & ss) { if this != &ss) {if(cStr != NULL) {delete[] cStr; cStr = NULL;len=0; }

  47. Overloading Various Operators Overloading assignment operator: String & string ::operator =(string & ss) { if (this!=&ss) { if (cstr!=NULL) { delete [] cstr; cstr=NULL; len=0; } if (ss.cstr!=NULL) { len=ss.len; cstr=new char[len+1]; strcpy(cstr,ss.cstr); } } return *this; }

  48. (i)If LHS.cStr =NULL and RHS.cStr =NULL • If LHS.cStr =NULL, then the first inner ‘if’ fails and the corresponding if block does not execute. If RHS.cStr =NULL then the second inner ‘if’ fails and the block does not execute. • The entire function does not do anything except that it returns the calling object by reference. The value of LHS operand remains unchanged.

  49. (ii)If LHS.cStr =NULL and RHS.cStr !=NULL If LHS.cStr =NULL, then the first inner ‘if’ fails and the corresponding if block does not execute. If RHS.cStr =!NULL then the second inner ‘if’ (if(ss.cStr!=0)) succeeds and the corresponding ‘if’block executes. It does the following: (i) correctly sets the value of len member of the calling object to be equal to the length of the memory block that will hold a copy of the string at which ‘cStr’ member of the RHS object is pointing. (ii) allocates just enough memory to hold a copy of the string at which the cStr member of the RHS object is pointing and makes cStr of LHS object point at it • Copies the string at which the cStr of RHS object is pointing in to the memory block at which the cStr of LHS object is pointing.

  50. (iii) If LHS.cStr !=NULL and RHS.cStr =NULL then the first inner ‘if’ succeeds and the corresponding if block executes. • It deallocates the memory the block at which cStr of LHS object points, sets its value to NULL and sets the value of the ‘len’ member of LHS object to ‘0’. If RHS.cStr=NULL then the second inner ‘if’ fails and the corresponding if block does not execute. • If LHS.cStr !=NULL and RHS.cStr !=NULL then the first inner block succeeds and executes.