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
Numberclass has a private member variablevalueto 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 theNumberclass. It is declared as a constant member function using theconstkeyword 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
Numberobject is created with the negation of the originalvalue. The negated value is obtained by using the unary minus operator (-) on thevaluemember variable.Line 16–19: The
display()member function is also defined within theNumberclass to display the value of theNumberobject. 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 theNumberclass callednumis created with10as the initial value. Then, the unary minus operator is applied tonumusing the syntax-num. The result is assigned to anotherNumberobject callednegNum.Line 26–27: Finally, the
display()function is called on bothnumandnegNumto print their respective values. The output demonstrates that the unary minus operator correctly negates the value ofnum, resulting in-10fornegNum.
Note: Why are we using the
constkeyword? By defining the overloaded unary minus operator as a constant member function using theconstkeyword, the operator can be used on constant objects and guarantees that the object's state remains unaltered. Thethispointer, which is an implicit pointer to the current object, refers to the object on which the operator is invoked. Theconstqualifier ensures that thethispointer is received as aconstpointer, enabling the invocation ofconstmember functions and access toconstdata 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
valuemember variable. Additionally, the global functionconst Number operator-(const Number&)for the unary operator takes one parameter.The
operator-()function works by creating a newNumberobject 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
Numberwith an integer member variable calledvalue. We then overload the addition (+) operator outside the class using a nonmember function. The operator function takes twoNumberobjects asconstreferences and returns a newNumberobject with the sum of their values. In themain()function, we create twoNumberobjectsnum1andnum2with values5and10, respectively. We then use the addition operator to addnum1andnum2, storing the result in thesumvariable. 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 declaredconstbecause 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.valueandthis->value.