Home / Articles / Introduction to Operator Overloading
Introduction to Operator Overloading
What Is Operator Overloading?
In C, operators can be applied to basic data types but not to user-defined ones. In C++, you can define functions that are called when an operator is applied to a user-defined type. This mechanism is called operator overloading.
The format for defining an operator overload function is:
return_value operator<operator_symbol>(argument_list)
For example, to overload > for a packet structure (comparing by timestamp):
bool packet::operator>(packet p)
{
if (difftime(time, p.time) < 0)
return false;
else
return true;
}
The statement if (p1 > p2) is then interpreted by the compiler as if (p1.operator>(p2)). In general, X + Y is interpreted as X.operator+(Y).
Overloading as Member Functions
#include <iostream>
using namespace std;
class square
{
int length;
public:
square(int length) { this->length = length; }
square operator+(int offset);
square operator+(square &s);
int getLength() { return length; }
int getArea() { return length * length; }
};
square square::operator+(int offset)
{
square temp(this->length);
temp.length += offset;
return temp;
}
square square::operator+(square &s)
{
square temp(this->length);
temp.length += s.length;
return temp;
}
int main()
{
square s1(10), s2(20);
cout << s1.getLength() << "\n"; // 10
s1 = s1 + 10;
cout << s1.getLength() << "\n"; // 20
s1 = s1 + s2;
cout << s1.getLength() << "\n"; // 40
return 0;
}
Returning an object of the same type allows chaining: s1 = s1 + s2 + 10.
Limitation: with member functions, the first operand must be of the user-defined type. s1 = s1 + 10 works, but s1 = 10 + s1 does not.
Maintaining Operator Semantics
The return type of an overloaded operator function is not enforced by the compiler — you could overload + to return bool. However, it is the programmer's responsibility to ensure that the operator's semantics are preserved. A + operator should perform addition and return a result of the appropriate type.
Overloading Unary Operators (Member Functions)
Prefix Operators
Prefix operators are overloaded with an empty argument list:
square square::operator++()
{
this->length++;
return *this;
}
Postfix Operators
Postfix operators require a dummy int parameter to distinguish them from prefix:
square square::operator++(int ignore)
{
square temp = *this;
this->length++;
return temp; /* Return old value */
}
Complete example with both prefix and postfix ++:
int main()
{
square s1(10), s2(20);
s2 = s1++; /* Postfix: s2 gets old value of s1 */
cout << s1.getLength() << "\n"; // 11
cout << s2.getLength() << "\n"; // 10
return 0;
}
Overloading as Global Functions
Operator overloads can be free (global) functions rather than member functions. In this case, both operands must be listed explicitly:
square operator+(square &s, int offset)
{
square temp(s.getLength() + offset);
return temp;
}
Global functions allow the first operand to be a basic type, enabling expressions like s1 = 2 + s1:
square operator+(int offset, square &s)
{
square temp(s.getLength() + offset);
return temp;
}
This is impossible with member functions because the first operand of a member operator+ must be the user-defined type.
Friend Functions
A global operator function can be declared as a friend of the class, granting it direct access to private members:
class square
{
int length;
public:
square(int length) { this->length = length; }
int getLength() { return length; }
friend square operator+(int offset, square &s);
};
square operator+(int offset, square &s)
{
square temp(s.length + offset); /* Can access private 'length' */
return temp;
}
Declaring a friend implies a strong coupling between the function and the class. Only use friend functions when direct access to private members is genuinely required and public accessor functions are insufficient or unavailable.
Overloading Unary Operators (Global Functions)
For global functions, the operand is passed as an explicit parameter:
// Prefix increment
square operator++(square &s)
{
s.setLength(s.getLength() + 1);
return s;
}
For the postfix version, add the dummy int parameter:
// Postfix increment
square operator++(square &s, int ignore)
{
square temp = s;
s.setLength(s.getLength() + 1);
return temp;
}