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

Course Content

C++ OOP

C++ OOP

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

book
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:

overloading.h

overloading.h

copy
1
return_type operator operator_symbol(parameters);

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.

Member.h

Member.h

Friend.h

Friend.h

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's possible to overload these operators, it is by no means necessary to overload all of them for your classes.

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 or from the stream.

Point.h

Point.h

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 like std::cout. This feature is especially useful for enhancing the readability and usability of your code when working with custom data types.

Note
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.

main.cpp

main.cpp

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; }

The operator is overloaded 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. The + operator can be replaced with -, *, /, or %, with corresponding adjustments to the implementation logic.

Increment and Decrement

Both the prefix and postfix increment and decrement operators (++ and --) can be overloaded for custom classes. Let's begin with the prefix version:

main.cpp

main.cpp

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
Note

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

As you can see, overloading the prefix increment and decrement operators is straightforward. However, it gets trickier with the postfix versions. Remember, there’s a difference in the order of execution between prefix and postfix operations.

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

main.cpp

main.cpp

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
Note

The integer parameter is passed without a name only to signal to the compiler that the postfix increment operator is being overloaded. This is necessary because the declarations for prefix and postfix operators are otherwise identical.

In the postfix increment operator implementation, the original value of the object is stored in a temporary variable (temp). The current object is then incremented, but the operator returns the value stored in temp. This means the variable is incremented, but the change takes effect only in the next expression, as the operator returns the original value.

question mark

What does operator overloading mean?

Select the correct answer

Everything was clear?

How can we improve it?

Thanks for your feedback!

SectionΒ 5. ChapterΒ 4

Ask AI

expand

Ask AI

ChatGPT

Ask anything or try one of the suggested questions to begin our chat

course content

Course Content

C++ OOP

C++ OOP

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

book
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:

overloading.h

overloading.h

copy
1
return_type operator operator_symbol(parameters);

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.

Member.h

Member.h

Friend.h

Friend.h

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's possible to overload these operators, it is by no means necessary to overload all of them for your classes.

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 or from the stream.

Point.h

Point.h

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 like std::cout. This feature is especially useful for enhancing the readability and usability of your code when working with custom data types.

Note
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.

main.cpp

main.cpp

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; }

The operator is overloaded 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. The + operator can be replaced with -, *, /, or %, with corresponding adjustments to the implementation logic.

Increment and Decrement

Both the prefix and postfix increment and decrement operators (++ and --) can be overloaded for custom classes. Let's begin with the prefix version:

main.cpp

main.cpp

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
Note

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

As you can see, overloading the prefix increment and decrement operators is straightforward. However, it gets trickier with the postfix versions. Remember, there’s a difference in the order of execution between prefix and postfix operations.

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

main.cpp

main.cpp

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
Note

The integer parameter is passed without a name only to signal to the compiler that the postfix increment operator is being overloaded. This is necessary because the declarations for prefix and postfix operators are otherwise identical.

In the postfix increment operator implementation, the original value of the object is stored in a temporary variable (temp). The current object is then incremented, but the operator returns the value stored in temp. This means the variable is incremented, but the change takes effect only in the next expression, as the operator returns the original value.

question mark

What does operator overloading mean?

Select the correct answer

Everything was clear?

How can we improve it?

Thanks for your feedback!

SectionΒ 5. ChapterΒ 4
some-alt