Hey guys! It’s the end of the week. Which means, another tutorial! Last couple weeks, we explored the Monte Carlos method, but this time, let’s change it up a little bit. Instead, we’ll be looking at some C++ operators, and more specifically, overloading them.
Prequisites:
OOP
'this' pointer
operators
Introduction
What are overloading operators? Well take this example:
class ExampleClass
{
private:
int value;
};
ExampleClass exampleObject;
exampleObject += 5; // error!
We get an error! Why? Well adding 5 to an object? What does that mean? But how do we add a number to value? Well the attribute is private, so our only choose are methods.
class ExampleClass
{
private:
int value;
public:
void add(int addValue)
{
value += addValue;
}
};
ExampleClass exampleObject;
exampleObject.add(5);
Well, that's good an all, but this is C++! There has to be a better way. Overloading operators.
class ExampleClass
{
private:
int value;
public:
// method - boring!
void add(int addValue)
{
value += addValue;
}
// overloading operator - much better!
void operator += (int addValue)
{
value += addValue;
}
};
int main()
{
ExampleClass exampleObject;
exampleObject.add(5); // methods? pfff... get outta here!
exampleObject += 5; // overloading operators? much better
}
Don't worry about the syntax for now. Just know that overloading operators change the behavior of normal operators. Now, the compiler doesn't see it as adding 5 to the object, but rather adding 5 to value.
Ready yourself to trash all your getters and setters.
The Basics
Let's start off by taking a look at the previous example.
class ExampleClass
{
private:
int value;
public:
// method
void add(int addValue)
{
value += addValue;
}
// overloaded operator
void operator += (int addValue)
{
value += addValue;
}
};
Notice how the method and overloaded operator are very similar. An overloaded operator starts off with it's return type (it's usually void, itself, or bool), then followed by the keyword operator, then the actual operator itself, and a parameter if required. Then inside the overloaded operator function, just do what you would normally do.
Here's another example.
class ExampleClass
{
private:
int value;
public:
// prefix increment
// also works for prefix decrement
ExampleClass operator ++ ()
{
value += addValue;
return *this;
}
};
This time we overloaded the prefix increment. This means we can do stuff like this:
ExampleClass exampleObject;
++exampleObject;
Notice how the return type is the object. That's because we use the increment like this:
// returns itself, which doesn't really do anything
// by itself
++exampleObject;
// returns itself, which is needed here
// 'std::cout' cannot print a void type
std::cout << ++exampleObject;
So in the first example, we incremented the object. The object returned itself, but it wasn't being used by anything, so the return type isn't needed there.
But, the second example saw us printing the object, which means we needed a return type there. That's why the increment operator needs a return type.
Let's look at another example.
class ExampleClass
{
private:
int value;
public:
bool operator > (const int compareValue)
{
return (value > compareValue);
}
};
int main()
{
// ignore syntax shortcomings for now
ExampleClass exampleObject;
if (exampleObject > 5)
std::cout << "is bigger";
}
As you can see, this operator overload returns type bool, because it's making a comparison. Also, I added the const there because I'm trying to get into the habit of using const cause... idk, better programming practice?
Now hopefully you guys get the jist of things. Now were going to take a look at what we're going to take a look at :)
Unary Operator - operates on one value
++ (pre- and postfix) -- (pre- and postfix) conversion types
Notice how the return type is the object. This is because we use increments like this: cout << ++value;. If it didn't return anything, then cout would be printing a void value.
Conversion Types
class squid
{
private:
int legs;
public:
// converts object to `int` (doesn't have to be `int`, could be whatever you want!)
operator int ()
{
return legs;
}
};
int main()
{
squid dynamicSquid;
cout << dynamicSquid; // this works!
int value = dynamicSquid; // this also works!
}
Notice how the coversion operator just turns the object into an int. It's kinda special since it doesn't have a return type.
Oh, and just a side note, the conversion operator is very powerful. In some cases, that's the only overloaded operator you'll need! Because remeber, it takes an object, and turns it into an 'int'. Very useful.
Binary Operators
Addition Operator
class squid
{
private:
int legs;
public:
squid operator + (int addValue) // same for sub, div, mult, and mod
{
return legs + addValue;
}
};
Returns an object for the same reason that the increments return an object.
Assignment Operators
class squid
{
private:
int legs;
public:
void operator += (int addValue) // same for sub, add, mult, div, and mod
{
legs += addValue;
}
};
Notice how the return type is void. This is because we don't need to return a value when working with assignment operators.
Comparison Operators
class squid
{
private:
int legs;
public:
bool operator == (int compareValue) // same for `!=`, `>`, `<`, `<=`, and `>=`
{
return legs == compareValue;
}
};
The return type is expected.
Subscript Operator
class squid
{
private:
string colour;
public:
const char operator [] (int index)
{
// this code is incomplete! always make sure you check whether or not the index is withing range!
return colour[index];
}
};
int main()
{
squid dynamicSquid;
cout << dynamicSquid[2];
}
Again, doesn't return a type because it doesn't need too.
Real Example
Okay, now you know what overloading operators are, let's take a look at a real example.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class squid
{
private:
string name;
public:
vector<string> colours;
squid(string _name)
: name(_name) {}
// conversion type - I'm using this for 'cout'
operator const char* ()
{
string output = "name: " + name;
// converts string to const char*
return output.c_str();
}
string operator [] (size_t index)
{
if (index < colours.size())
return colours[index];
}
// used to insert elements in 'colours' array
void operator () (string squidType)
{
colours.push_back(squidType);
}
// used to compare two squids
bool operator == (squid compareSquid)
{
return (name == compareSquid.name);
}
};
int main()
{
squid dynamicSquid("Dynamic Squid");
squid fuzzySquid("Fuzzy Squid");
// using the comparision operator
if (dynamicSquid == fuzzySquid)
cout << "They have the same name!\n";
// using the function operator
dynamicSquid("pink");
dynamicSquid("blue");
dynamicSquid("red");
cout << "Here are my favourite colours:\n";
for (size_t a = 0; a < dynamicSquid.colours.size(); ++a)
cout << dynamicSquid[a] << '\n'; // this is possible due to conversion operator
}
Oh, and what's up with all the squids? Well I'm making my own data type actually called "squid" (coming out soon), so yeah...
And that's it! Most of the operators you'll ever need. If there's one that I missed, please let me know so I can add it in.
Overloading Operators in C++!
Hey guys! It’s the end of the week. Which means, another tutorial! Last couple weeks, we explored the Monte Carlos method, but this time, let’s change it up a little bit. Instead, we’ll be looking at some C++ operators, and more specifically, overloading them.
Prequisites:
Introduction
What are overloading operators? Well take this example:
We get an error! Why? Well adding 5 to an object? What does that mean? But how do we add a number to
value
? Well the attribute is private, so our only choose are methods.Well, that's good an all, but this is C++! There has to be a better way. Overloading operators.
Don't worry about the syntax for now. Just know that overloading operators change the behavior of normal operators. Now, the compiler doesn't see it as adding
5
to the object, but rather adding5
tovalue
.Ready yourself to trash all your getters and setters.
The Basics
Let's start off by taking a look at the previous example.
Notice how the method and overloaded operator are very similar. An overloaded operator starts off with it's return type (it's usually
void
,itself
, orbool
), then followed by the keywordoperator
, then the actual operator itself, and a parameter if required. Then inside the overloaded operator function, just do what you would normally do.Here's another example.
This time we overloaded the prefix increment. This means we can do stuff like this:
Notice how the return type is the object. That's because we use the increment like this:
So in the first example, we incremented the object. The object returned itself, but it wasn't being used by anything, so the return type isn't needed there.
But, the second example saw us printing the object, which means we needed a return type there. That's why the increment operator needs a return type.
Let's look at another example.
As you can see, this operator overload returns type
bool
, because it's making a comparison. Also, I added theconst
there because I'm trying to get into the habit of usingconst
cause... idk, better programming practice?Now hopefully you guys get the jist of things. Now were going to take a look at what we're going to take a look at :)
Unary Operator - operates on one value
++
(pre- and postfix)--
(pre- and postfix)conversion types
Binary Operators - operates on two values
==
,!=
,<
,>
,<=
,>=
+
,-
,/
,*
,%
+=
,-=
,/=
,*=
,%=
[]
(subscript operator)()
(function operator)Unary Operators
Increments and Decrements
Notice how the return type is the object. This is because we use increments like this:
cout << ++value;
. If it didn't return anything, thencout
would be printing avoid
value.Conversion Types
Notice how the coversion operator just turns the object into an int. It's kinda special since it doesn't have a return type.
Oh, and just a side note, the conversion operator is very powerful. In some cases, that's the only overloaded operator you'll need! Because remeber, it takes an object, and turns it into an 'int'. Very useful.
Binary Operators
Addition Operator
Returns an object for the same reason that the increments return an object.
Assignment Operators
Notice how the return type is void. This is because we don't need to return a value when working with assignment operators.
Comparison Operators
The return type is expected.
Subscript Operator
The return type is expected.
Function Operator
Again, doesn't return a type because it doesn't need too.
Real Example
Okay, now you know what overloading operators are, let's take a look at a real example.
Oh, and what's up with all the squids? Well I'm making my own data type actually called "squid" (coming out soon), so yeah...
And that's it! Most of the operators you'll ever need. If there's one that I missed, please let me know so I can add it in.
And don't forget to upvote :)
@DynamicSquid Yes, of course!