Operator Overloading in C++
Operator Overloading in C++
In C++, we can make operators to work for user defined classes. For example, we can overload an operator ‘+’ in a class like String so that we can concatenate two strings by just using +.
Other example classes where arithmetic operators may be overloaded are Complex Number, Fractional Number, Big Integer, etc.
Other example classes where arithmetic operators may be overloaded are Complex Number, Fractional Number, Big Integer, etc.
A simple and complete example
#include<iostream> using namespace std; class Complex { private : int real, imag; public : Complex( int r = 0, int i =0) {real = r; imag = i;} // This is automatically called when '+' is used with // between two Complex objects Complex operator + (Complex const &obj) { Complex res; res.real = real + obj.real; res.imag = imag + obj.imag; return res; } void print() { cout << real << " + i" << imag << endl; } }; int main() { Complex c1(10, 5), c2(2, 4); Complex c3 = c1 + c2; // An example call to "operator+" c3.print(); } |
Output:
12 + i9
What is the difference between operator functions and normal functions?
Operator functions are same as normal functions. The only differences are, name of an operator function is always operator keyword followed by symbol of operator and operator functions are called when the corresponding operator is used.
Following is an example of global operator function.
Operator functions are same as normal functions. The only differences are, name of an operator function is always operator keyword followed by symbol of operator and operator functions are called when the corresponding operator is used.
Following is an example of global operator function.
#include<iostream> using namespace std; class Complex { private : int real, imag; public : Complex( int r = 0, int i =0) {real = r; imag = i;} void print() { cout << real << " + i" << imag << endl; } // The global operator function is made friend of this class so // that it can access private members friend Complex operator + (Complex const &, Complex const &); }; Complex operator + (Complex const &c1, Complex const &c2) { return Complex(c1.real + c2.real, c1.imag + c2.imag); } int main() { Complex c1(10, 5), c2(2, 4); Complex c3 = c1 + c2; // An example call to "operator+" c3.print(); return 0; } |
an we overload all operators?
Almost all operators can be overloaded except few. Following is the list of operators that cannot be overloaded.
Almost all operators can be overloaded except few. Following is the list of operators that cannot be overloaded.
. (dot) :: ?: sizeof
Why can’t . (dot), ::, ?: and sizeof be overloaded?
Most operators can be overloaded by a programmer. The exceptions are
Most operators can be overloaded by a programmer. The exceptions are
. (dot) :: ?: sizeof
There is no fundamental reason to disallow overloading of ?:. I just didn't see the need to introduce the special case of overloading a ternary operator. Note that a function overloading expr1?expr2:expr3 would not be able to guarantee that only one of expr2 and expr3 was executed.
Sizeof cannot be overloaded because built-in operations, such as incrementing a pointer into an array implicitly depends on it. Consider:
X a[10]; X* p = &a[3]; X* q = &a[3]; p++; // p points to a[4] // thus the integer value of p must be // sizeof(X) larger than the integer value of q
Thus, sizeof(X) could not be given a new and different meaning by the programmer without violating basic language rules.
In N::m neither N nor m are expressions with values; N and m are names known to the compiler and :: performs a (compile time) scope resolution rather than an expression evaluation. One could imagine allowing overloading of x::y where x is an object rather than a namespace or a class, but that would - contrary to first appearances - involve introducing new syntax (to allow expr::expr). It is not obvious what benefits such a complication would bring.
Operator . (dot) could in principle be overloaded using the same technique as used for ->. However, doing so can lead to questions about whether an operation is meant for the object overloading . or an object referred to by . For example:
class Y { public: void f(); // ... }; class X { // assume that you can overload . Y* p; Y& operator.() { return *p; } void f(); // ... }; void g(X& x) { x.f(); // X::f or Y::f or error? }
Important points about operator overloading
1) For operator overloading to work, at leas one of the operands must be a user defined class object.
1) For operator overloading to work, at leas one of the operands must be a user defined class object.
2) Assignment Operator: Compiler automatically creates a default assignment operator with every class. The default assignment operator does assign all members of right side to the left side and works fine most of the cases (this behavior is same as copy constructor). See this for more details.
3) Conversion Operator: We can also write conversion operators that can be used to convert one type to another type.
#include <iostream> using namespace std; class Fraction { int num, den; public : Fraction( int n, int d) { num = n; den = d; } // conversion operator: return float value of fraction operator float () const { return float (num) / float (den); } }; int main() { Fraction f(2, 5); float val = f; cout << val; return 0; } |
Output:
0.4
Overloaded conversion operators must be a member method. Other operators can either be member method or global method.
4) Any constructor that can be called with a single argument works as a conversion constructor, means it can also be used for implicit conversion to the class being constructed.
#include<iostream> using namespace std; class Point { private : int x, y; public : Point( int i = 0, int j = 0) { x = i; y = j; } void print() { cout << endl << " x = " << x << ", y = " << y; } }; int main() { Point t(20, 20); t.print(); t = 30; // Member x of t becomes 30 t.print(); return 0; } |
Output:
x = 20, y = 20 x = 30, y = 0
Comments
Post a Comment