Overridable Operators
- It is the mechanism of adding special meaning to an operator.
- It provides flexible option for extension of the meaning of the operator when applied to user defined data types.
- All operators are not overloadable.
- The operator that can be overloaded are as follows:
1. Member access operator (.)
2. Pointer to member access operator (.*)
3. Scope resolution operator (::)
4. Size of operator
5. Conditional operator (?:)
6. Runtime type information operator (typeid)
- All other operators can be overloaded.
Syntax of Operator Overloading
- Operator function must be defined.
- Operator function:
return_type operator operator_symbol(arg_list) { //body }
- As a member function:
class class_name { //.................. public: return_type operator operator_symbol(arg); };
return_type class_name :: operator operator_symbol (arg)
{
//body
}
- For non-member friend function:
class class_name { //............ public: friend return_type operator operator_symbol (arg, arg); };
return_type operator operator_symbol(arg, arg)
{
//body
}
- The non-member operator function takes one more argument than the member operator function.
- For unary operator overloading, member function has no argument and non member function has one argument.
- For binary operator overloading, member function has one argument and non member function has two argument.
Rules of Operator Overloading
- After overloading, the meaning of operator can not be changed. So, use similar meaning only.
- The precedence, associativity and other syntactic characteristics of overloaded operator can not be changed.
- Use operator overloading only when necessary.
- Avoid ambiguity.
- New operators can not be created.
- Operator for basic types can not be created.
Unary Operator Overloading
- It is overloaded with non-static member function with no argument or non-member function taking one argument.
- As a non-static member function:
class class_name { //........... public: return_type operator operator_symbol(); //Prefix operator return_type operator operator_symbol(int); //Postfix operator //.................. };
return_type class_name :: operator operator_symbol() //Prefix operator overloading definition
{
//..........
}
return_type class_name :: operator operator_symbol(int) //Postfix operator overloading definition
{
//..........
}
- As a non-member function:
return_type operator operator_symbol(class_name) //Prefix operator overloading definition { //.......... }
return_type operator operator_symbol(class_name, int) //Postfix operator overloading definition
{
//..........
}
Overloading operator for prefix ++
#include
class counter { unsigned int count; public: counter() {count = 0;} int ret_count() { return count; } void operator ++ () { count++; } };
int main() { counter c1, c2; cout << "c1 = " << c1.ret_count << "c2 = " << c2.ret_count; ++c1; ++c2; ++c2; cout << "c1 = " << c1.ret_count << "c2 = " << c2.ret_count; return 0; }
Overloading operator for postfix ++
#include
class counter { unsigned int count; public: counter() {count = 0;} counter(unsigned int n) : count(n) {} int ret_count() { return count; } counter operator ++ (int); };
counter counter :: operator ++ (int) { return counter(count++); }
int main() { counter c1, c2; cout << "c1 = " << c1.ret_count << "c2 = " << c2.ret_count; c1++; c2++; c2++; cout << "c1 = " << c1.ret_count << "c2 = " << c2.ret_count; return 0; }
Binary Operator Overloading
- By non static member function taking one argument or a non member function taking two arguments.
Overloading + operator
#include
class complex { float real, imag; public: complex() {
} complex(float rel, float img) { real = rel; imag = img; } void display() { cout << real << " + i" << imag; } complex operator + (complex c); };
complex complex :: operator + (complex c) { complex temp; temp.real = real + c.real; temp.imag = imag + c.imag; return temp; }
int main() { complex c1, c2, c3; c1 = complex (4.4, 3.6); c2 = complex (2.4, 3.5); c3 = c1 + c2; c3.display(); return 0; }
Data Conversion
Conversion from Basic to User Defined Data Type
- It is done either by constructor or by overloading cast operator.
#include
class celcius { float temp; public: celcius() {} celcius(float ftemp) { temp = (ftemp - 32) * 5 / 9; } void show() { cout << "Temp in celcius = " << temp; } };
int main() { celcius cel; float fer; cout << "Enter temp in fahrenheit : "; cin >> fer; cel = fer; // Basic to user defined cel.showtemp(); return 0; }
Conversion from User Defined to Basic
- It is done by overloading cast operator.
#include
class celcius { float temp; public: celcius() { temp = 0; } void gettemp() { cout << "Temp in celcius = "; cin >> temp; } operator float () { float fer; fer = (temp * 9 / 5) + 32; return (fer); } };
int main() { celcius cel; float fer; cel.gettemp(); fer = cel; cout << "Temp in Fahrenheit = " << fer; return 0; }
Conversion Between User Defined Type
- Conversion function can be defined in destination or source.
- To be defined in destination, one argument constructor is used.
- To be defined in source, cast operator function should be overloaded.
1. In Destination
// Program to convert polar coordinates to cartesian coordinates. #include #include
class polar { private: float radius, angle; public: polar() {} polar(float rad, float ang) { radius = rad; angle = ang; } float return_rad() { return radius; } float return_ang() { return angle; } void display() { cout << "(" << radius << "," << angle << ")"; } };
class cartesian { private: float x, y; public: cartesian() { x = 0; y = 0; } cartesian(float x0, float y0) { x = x0; y = y0; } cartesian(polar p) { x = p.return_rad() * cos(p.return_ang()); y = p.return_rad() * sin(p.return_ang()); } void display() { cout << "(" << x << "," << y << ")"; } };
int main() { polar pol(10.0, 0.7853); cartesian cart; cart = pol; cart.display(); return 0; }
2. In Source
// Program to convert polar coordinates to cartesian coordinates. #include #include
class cartesian { private: float x, y; public: cartesian() { x = 0; y = 0; } cartesian(float x0, float y0) { x = x0; y = y0; } void display() { cout << "(" << x << "," << y << ")"; } };
class polar { private: float radius, angle; public: polar() { radius = 0; angle = 0; } polar(float rad, float ang) { radius = rad; angle = ang; } operator cartesian() { float x = static_cast (radius * cos(angle)); float y = static_cast (radius * sin(angle)); return cartesian(x, y); } void display() { cout << "(" << radius << "," << angle << ")"; } };
int main() { polar pol(10.0, 0.7853); cartesian cart; cart = pol; cart.display(); return 0; }
Explicit Constructors
- The implicit conversion can be prevented by declaring explicit constructor.
- The keyword 'explicit' is used.
- It can be invoked explicitly.
class test { int data; public: test() { data = 0; } explicit test(int n) { data = n; } };
// Called as:
test t1(2);
- by SURAJ AWAL
Ⓒ Copyright ESign Technology 2019. A Product of ESign Technology. All Rights Reserved.