Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Operator Overloading | Polymorphism Overview
C++ OOP
course content

Contenido del Curso

C++ OOP

C++ OOP

1. Fundamentals of OOP
2. Constructors and Destructors
3. Encapsulation Overview
4. Inheritance Overview
5. Polymorphism Overview

Operator Overloading

Operator overloading is a powerful feature in object-oriented programming languages that allows you to redefine the behavior of operators for user-defined classes. By overloading operators, you can provide custom implementations for operations involving objects of your class, enabling more intuitive and expressive code.

The syntax of operator overloading

Overloading s achieved by defining special member functions or friend functions that implement the desired behavior for the operator. The syntax for overloading operators varies depending on operator you want to overload. The general one looks like this:

The syntax, or more specifically, the number of parameters and returning type, also depends on whether you're overloading operators as member functions or friend functions. Consider the following two examples:

h

Member

h

Friend

copy
123456
class Example { public: Example operator+ (const Example& other) { // Define behavior for operator+ } };

The table of operators that can be overloaded

Here is a table listing all the operators that can be overloaded. However, it's important to note that while it is s possible to overload these operators, it is completely not necessary to overload all of them for your classes.

Operators
Purpose
Example
()
Function call
function()
[]
Array subscripting
array[index]
++ --
Increment/decrement
++a, a--, etc.
+ - * / %
Arithmetic operations
a + b, a - b, etc.
+= -= *= /=
Assignment operations
a += b, a -= b, etc.
== != < >
Comparison operations
a == b, a < b, etc.
<< >>
Stream insertion/extraction
cout << a, cin >> a

We will focus on the most commonly used operators, including stream insertion and extraction, arithmetic operators, increment and decrement operators.

Overloading stream insertion operators

To overload the << and >> operators for a class, you typically define a friend function or a member function that takes an output stream (std::ostream&) or input stream(std::istream&) as the left operand and an object of your class as the right operand. This function then formats the object's data and streams it to the output stream.

h

Point

copy
123456789101112131415
class Point { public: friend std::ostream& operator<<(std::ostream& out, const Point& point); friend std::istream& operator>>(std::istream& in, Point& point); private: int x, y; }; std::ostream& operator<<(std::ostream& out, const Point& point) { return out << "x: " << point.x << ", y: " << point.y << std::endl; } std::istream& operator>>(std::istream& in, Point& point) { return in >> point.x >> point.y; }

Overloading stream insertion operators, such as <<, allows you to define custom output behavior for objects of your classes when they are streamed to an output stream, such as std::cout. This feature is particularly useful for enhancing the readability and usability of your code when dealing with custom data types.

Note

Overloading the << operator for output stream is more common than overloading the >> operator for input stream, because input operations with >> can be more error-prone.

Overloading arithmetic operators

You can overload other arithmetic operators (-, *, /, %) in a similar manner to perform custom operations with your user-defined types.

cpp

main

copy
12345678910111213141516171819202122
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} Point operator+(const Point& other) { return Point(x + other.x, y + other.y); } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p = Point(2, 4) + Point(2, 6); std::cout << p.getX() << ' ' << p.getY() << std::endl; }

In this example, we overloade as a member function of the Point class. It takes another Point object as a parameter and returns a new Point object that represents the sum of the two points. You can change + for -, *, /, % and adjust a implementation logic a bit.

Increment and Decrement

You can overload both the prefix and postfix increment and decrement operators (++ and --) for your custom classes. Let's begin with prefix:

cpp

main

copy
123456789101112131415161718192021222324
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} // Prefix increment operator (++point) Point& operator++() { ++x; ++y; return *this; } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p(2, 2); ++p; std::cout << p.getX() << ' ' << p.getY() << std::endl; }

Note

The decrement operator is overloaded in a similar manner to the increment operator, with the use of the -- operator and subtraction operation.

As you see there is nothing hard in overloading prefix increment and decrement. However it is gets trickier when it comes to postfix one. As you remember there is an order of execution of postfix and prefix increment.

Operator
Expression
Output (Assuming x = 5)
Order of Execution
++Prefix
++x
6
Increment, then use
Postfix++
x++
5
Use, then increment
--Prefix
--x
4
Decrement, then use
Postfix--
x--
5
Use, then decrement

When overloading postfix increment and decrement we also has to implement the order of execution feature. It will look something like this:

cpp

main

copy
1234567891011121314151617181920212223242526
#include <iostream> class Point { public: Point(int xCoord, int yCoord) : x(xCoord), y(yCoord) {} // Postfix increment operator (point++) Point operator++(int) { Point temp = *this; // Creating a temp variable ++(this->x); // Incrementing original Point's x ++(this->y); // Incrementing original Point's y return temp; // Returning created temp variable } int getX() { return x; } int getY() { return y; } private: int x, y; }; int main() { Point p(2, 2); p++; std::cout << p.getX() << ' ' << p.getY() << std::endl; }

Note

The integer parameter is passed without an argument name solely to signify to the compiler that it is the postfix increment operator being overloaded. It is necessary because the declaration of prefix and postfix operators does not differ in any other way.

In the postfix increment operator implementation, the original value of the object is stored in a temporary variable (temp). While the current object is then incremented, the value returned by the operator is the one stored in temp. So, the variable is incremented, but the incrementation takes effect only in the next expression, as the operator returns the original value.

What does operator overloading mean?

Selecciona la respuesta correcta

¿Todo estuvo claro?

Sección 5. Capítulo 4
We're sorry to hear that something went wrong. What happened?
some-alt