Unary and Binary Operators
Learn the general syntax and implementation of unary and binary operators in programming, both inside and outside class definitions.
In C++, operators play a fundamental role in performing various operations on data. They can be broadly categorized into two types: unary operators, which take a single parameter, and binary operators, which work with two parameters. Each type of operator can serve a specific purpose in manipulating custom data types and their expressions.
Let’s explore these two categories in depth to gain a comprehensive understanding of how to effectively overload these functions and apply them to a user-defined data type.
Overloading unary operators
Unary operators act on a single operand. Here are some common unary operators:
Prefix and postfix increment (
++
,--
)Unary plus and minus (
+
,-
)Logical NOT (
!
)Function call operator (
()
)Others (
*
,&
,~
)
We can overload unary operators both inside and outside a class. When overloading inside a class, it’s common to use constant (const
) member functions to ensure the left argument is received as const
in the this
pointer.
Example: Overloading the unary minus (-
) operator inside and outside a class
#include <iostream>using namespace std;class Number{private:int value;public:Number(int val) : value(val) {}Number operator-() const{return Number(-value);}void display() const{cout << "Value: " << value << endl;}};int main() {Number num(10);Number negNum = -num; // Here we have called the -ve operatornum.display(); // Output: Value: 10negNum.display(); // Output: Value: -10return 0;}
In the UnaryInside.cpp
file:
Line 5–9: The
Number
class has a private member variablevalue
to store an integer value. The constructor initializes this value based on the provided argument.Line 11: The unary minus operator (
-
) is overloaded as a member function of theNumber
class. It is declared as a constant member function using theconst
keyword at the end of the function signature. This means that the operator function does not modify the state of the object on which it is called.Line 13: Inside the overloaded operator function, a new
Number
object is created with the negation of the originalvalue
. The negated value is obtained by using the unary minus operator (-
) on thevalue
member variable.Line 16–19: The
display()
member function is also defined within theNumber
class to display the value of theNumber
object. It is declared as a constant (const
) member function to ensure it does not modify the object’s state.Line 23–24: In the
main()
function, an instance of theNumber
class callednum
is created with10
as the initial value. Then, the unary minus operator is applied tonum
using the syntax-num
. The result is assigned to anotherNumber
object callednegNum
.Line 26–27: Finally, the
display()
function is called on bothnum
andnegNum
to print their respective values. The output demonstrates that the unary minus operator correctly negates the value ofnum
, resulting in-10
fornegNum
.
Note: Why are we using the
const
keyword? By defining the overloaded unary minus operator as a constant member function using theconst
keyword, the operator can be used on constant objects and guarantees that the object's state remains unaltered. Thethis
pointer, which is an implicit pointer to the current object, refers to the object on which the operator is invoked. Theconst
qualifier ensures that thethis
pointer is received as aconst
pointer, enabling the invocation ofconst
member functions and access toconst
data members within the operator function. It is always recommended to use operators functions as constants so that the callee object (the left of the operand) does not get updated even by mistake (yielding a logical error).
In the UnaryOutside.cpp
file:
Line 26–35: The class contains getter and setter functions to modify and access the
value
member variable. Additionally, the global functionconst Number operator-(const Number&)
for the unary operator takes one parameter.The
operator-()
function works by creating a newNumber
object and assigning values using either the setter or the constructor. To retrieve the value inside the passed parameter object, the getter function is utilized.
These are the two general ways of creating a unary operator. We may define the above-listed operators in any way for the user-defined data types. Don’t forget to change the definition of the parameter list passed corresponding to each unary operator.
We’ll look at some more examples of unary operator overloading when we discuss the string
library and implement the Matrix
case study. For now, we must comprehend the idea after making a unary operator function.
Overloading binary operators
Binary operators work on two operands. Some common binary operators include:
Arithmetic operators (
+
,-
,*
,/
,%
)Relational and equality operators (
==
,!=
,<
,>
,<=
,>=
)Logical operators (
&&
,||
)Assignment (
=
) and compound assignment operators (+=
,-=
,*=
,/=
,%=
)Array subscript operator (
[]
)Function call operator (
()
)Others (
<<
,>>
)
Like unary operators, binary operators can be overloaded inside and outside a class.
#include <iostream>using namespace std;class Number{private:int value;public:Number(int val) : value(val){}int getValue() const{return value;}Number operator+(const Number& num2)const{return Number(this->getValue() + num2.getValue());}};int main(){Number num1(5);Number num2(10);Number sum = num1 + num2;cout << "Sum: " << sum.getValue() << endl; // Output: Sum: 15return 0;}
In the OperatorOutside.cpp
file:
We define a class called
Number
with an integer member variable calledvalue
. We then overload the addition (+
) operator outside the class using a nonmember function. The operator function takes twoNumber
objects asconst
references and returns a newNumber
object with the sum of their values. In themain()
function, we create twoNumber
objectsnum1
andnum2
with values5
and10
, respectively. We then use the addition operator to addnum1
andnum2
, storing the result in thesum
variable. Finally, we display the sum using thegetValue()
member function.
Overloading compound assignment operators
Compound assignment operators combine arithmetic or logical operations with an assignment. Examples include +=
, -=
, *=
, /=
, %=
, |=
, &=
etc. Overloading compound assignment operators can simplify code and make it more readable.
Example: Overloading the compound addition assignment (+=
) operator
#include <iostream>using namespace std;class Number{private:int value;public:Number(int val) : value(val) {}Number& operator+=(const Number& other){value += other.value;return *this;}void display() const{cout << "Value: " << value << endl;}};int main() {Number num(5);num += Number(10);num.display(); // Output: Value: 15return 0;}
In the Operator+=Outside.cpp
file:
We’ve added the following global function:
Number& operator+=(Number& left, const Number& other)
The first parameter,
left
, is a nonconstant reference because it modifies the value of the left operand. The second parameter,other
, is a constant reference because it is not modified. Notice that for this, we need to have getters and setters implemented inside the class.
In the Operator+=Inside.cpp
file:
The
operator+=
function is a nonconstant member function.
Number& operator+=(const Number& other)
It operates on the current object (
*this
) and updates its value. It’s not declaredconst
because it modifies the callee object on which the function is invoked. We don’t need getters and setters for this implementation as the function is written inside the class, and the member attributes of both can be accessed throughother.value
andthis->value
.