Showing posts with label Overload. Show all posts
Showing posts with label Overload. Show all posts

C++ Operators Overloading

In this tutorial of our C++ course, we will learn how to use a very important tool in the C++ language, operator overloading.


The role of an operator

What the '+' operator does in the command:
2 + 2?

Easy. He adds, after all, is the addition operator.
Wrong. He is not the addition operator.
So what is it?

Depends on the use!

For example, with strings:
"Progressive" + "C++"

It will result in the string: "Progressive C++"

That is, the function of the '+' operator was concatenation, that is, to unite, to join two strings into one. You see, it is concatenating, there is no sense in 'adding text'. You add numbers, and with numbers, the '+' function is a mathematical addition.

That is, an operator can act in different ways, depending on how it is being used. It's called overloading.


What is Operator overloading for?

Let's suppose that you are the programmer of a company that manages several bands, among them you have the band 'IronMaiden', object of the class 'Band'. Your system also has the class "Member", where your objects are the members of each band.

Overloading operators in C++

Let's assume that candidate "BruceDickinson" will be hired and member "BlazeBayley" will leave the band.
With operator overloading, we can use the '+' operator in the expression:
  • IronMaiden = IronMaiden + BruceDickinson

As well as using the '-' in the command:
  • IronMaiden = IronMaiden - BlazeBayley

Look how curious: we are adding an object of type Band with an object of type Member. But, doesn't it make sense? One will enter and another will leave.

Another example, imagine that you are the programmer responsible for a large company.

When we hire, we are adding someone, so we can do an overloading to add an object of the Employee class with the object of the Company class, then there in your code, when this happens, there will be one more person on the payroll, one more person in one sector, etc.

And when we fire, we are subtracting someone, we can use the '-' operator to subtract an Employee object from the Company object, so in the code, in these cases, we will have to pay labor rights, another employee will have to keep the functions that the dismissed used to did, etc.

That is, we did an overload of operators '+' and '-', to have different meanings when we do operations with these objects. With the overloading operators, you do what you want with the objects, the operators will do what you define.

There are only 4 operators that cannot be overloaded:
  1.  .
  2.  .*
  3.  ::
  4.  ?:
The rest can, and should, overload, if it makes sense to your project. Let's learn how to do this in practice?

How to overload operators in C++

Let's create the Point class, to represent a point on the Cartesian plane. It receives two integers (coordinates) and has a function that shows these coordinates, see the Point class:

class Point
{
    private:
        int x, y;
    public:
        Point(int a, int b);
        void getPoint();
};

However, in vector algebra, a common operation is the sum of vectors, which is basically adding the coordinates of two points.
For example: (1,2) + (2,3) = (1 + 2, 2 + 3) = (3,5)

That is, the sum of two points is nothing more than the sum of the coordinates, separately.

So come on, implement this with overloading. The overloading header is the same as a function. In our case, it is:
  • Point operator+(Point p);
That is, it must always return the data type of the class, which is Point. Then we write "operator+" to overload the + operator, and finally, we put the type of data that will be added, in this case, it is another object of type Point.

Our code is:

#include <iostream>
using namespace std;

class Point
{
    public:
        int x, y;
        Point(int a, int b);
        void getPoint();
        Point operator+(Point p);
};

Point Point::operator+(Point p)
{
    x=x+p.x;
    y=y+p.y;

    return Point(x,y);
}

Point::Point(int a, int b)
{
    x=a;
    y=b;
}

void Point::getPoint()
{
    cout<<"("<<x<<","<<y<<")"<<endl;
}

int main()
{

    Point p1(1,2), p2(2,3);
    Point p3 = p1 + p2;
    p3.getPoint();

    return 0;
}

One way to understand this operation is to switch:
p3 = p1 + p2;

Per:
p3 = p1.operator+(p2);

It is as if the class had a function called operator+(), whose parameter is another object of type Point.

Operator Overloading Example in C++

We will now overload the operator '='
I want the following: when I equate a Point object with an integer, the coordinates must be equal to that integer.

That is, if I do:
p = 1, the coordinates of the object p must be (1,1)

See the code:

#include <iostream>
using namespace std;

class Point
{
    public:
        int x, y;
        Point(int a, int b);
        Point();
        void getPoint();
        Point operator+(Point p);
        void operator=(int n);
};
void Point::operator=(int n)
{
    x=n;
    y=n;
}
Point Point::operator+(Point p)
{
    x=x+p.x;
    y=y+p.y;

    return Point(x,y);
}

Point::Point()
{
    x=0;
    y=0;
}
Point::Point(int a, int b)
{
    x=a;
    y=b;
}

void Point::getPoint()
{
    cout<<"("<<x<<","<<y<<")"<<endl;
}

int main()
{

    Point p1(1,2), p2(2,3);
    Point p3 = p1 + p2;
    p3.getPoint();

    Point p4;
    p4=1;
    p4.getPoint();

    return 0;
}

Look what curious, we assign the object 'p4', which is a Point type, with an integer. It sounds crazy, it's like assign a car with an apple. But C++ allows this 'madness', you just need to make sense of it, and it does so through the overload of operators.

You know something crazy, compare if one object is bigger than another!
?

Relational Operator Overloading

A vector, in the Cartesian plane, is defined by two numbers (x, y)
Its size, called a module, is: d = sqrt (x² + y²)
That is, square root of: x² + y²

Let's create the myVector class to represent a vector, and compare if a vector v1 is greater than a vector v2, the code stays, that is, if v1> v2

However, v1 and v2 are objects of the myVector class, not numbers, so we cannot make this comparison directly, so we will have to overload the operator '>', for it to do another type of operation:

#include <iostream>
#include <cmath>
using namespace std;

class myVector
{
    public:
        int x, y;
        myVector(int a, int b);
        bool operator>(myVector v);
};

bool myVector::operator>(myVector v)
{
    float d1, d2;
    d1=sqrt(x*x + y*y);
    d2=sqrt(v.x*v.x + v.y*v.y);

    if(d1>d2)
        return true;
    else
        return false;
}

myVector::myVector(int a, int b)
{
    x=a;
    y=b;
}

int main()
{
    myVector v1(6,8), v2(3,4);

    if(v1 > v2)
        cout<<"The vector ("<<v1.x<<","<<v1.y<<") is bigger than ("<<v2.x<<","<<v2.y<<")"<<endl;
    else
        cout<<"The vector ("<<v1.x<<","<<v1.y<<") is less or equal than ("<<v2.x<<","<<v2.y<<")"<<endl;


    return 0;
}

In the case of the '>' operator, it always returns true or false, so the overload returns a bool.

Operator Overloading Exercise

If you have already graduated from high school, you know what complex numbers are. These are numbers like:
x = a + bi

Where 'a' is the real part and 'b' the imaginary part, as it is accompanied by the imaginary number 'i'.

Create a class that represents a complex number. It must perform the sum and product operation of complex numbers.

Sum:
x = a + bi
y = c + di
sum = x + y = (a + c) + (b + d) i

Product:
product = x * y = (ac − bd) + (ad + bc) i

Post your overloadings in the comments.

Constructor function overloading in C++

In this tutorial from our Progressive C++ course, we will learn about overloading the constructor functions.

Overload constructors in C++


Many constructors functions

You were hired by a university to create a system to help teachers, especially to work with students' grades.

As you took the Progressive C++ course, you will create a fantastic system, with several classes and objects, hardcore.
But let's take it easy.

Let's create a math class, called Math. For simplicity, she'll do just one operation: average two grades, one student, that's all.

The constructor function will tell the student's average right away.

See how our code looks:

#include <iostream>
using namespace std;

class Math
{
    public:
        Math(double, double);
};


Math::Math(double g1, double g2)
{
    cout<<"Average: "<<(g1+g2)/2<<endl;
}


int main()
{
    Math BruceDickinson(10, 8);

    return 0;
}

The result was 9 right, all nice and cool, and student Bruce Dickinson got a great average.

And speaking of market experience, it is SOOOO common for customers to be asking for changes, new features, etc. Get used to it, it is always requests and complaints.

In that case, the university now wants you to average 3 grades.

Time, it's very simple, just add one more parameter to the list of the constructor function, create the object with the 3 notes and send a bullet, that's it, our code looks like this:

#include <iostream>
using namespace std;

class Math
{
    public:
        Math(double, double, double);
};


Math::Math(double g1, double g2, double g3)
{
    cout<<"Average: "<<(g1+g2+g3)/3<<endl;
}


int main()
{
    Math NeilPeart(10, 9, 10);

    return 0;
}

Everything was fine and Neil Peart had an almost perfect average.

But then your university get in contact and says: look, there are students who will make two disciplines and students who will make three, that is, their system has to calculate the average in both cases.

And now? How will the constructor guess? One hour calculates the average by dividing by 2 and in the other example he divided by 3 because he had one more variable.

Create a class for each case? Of course not, as this is a complication.

Programming was made to make the world easier! This is where builder overloading comes in.


Constructors overloading in C++

C++ has a card up its sleeve: it allows you to create as many constructors as you want. That's right, functions with the same name.
But one thing has to be different: the list of parameters.

Example of a list of different parameters:

  • Math (double, double)
  • Math (double, int)
  • Math (int, double)
  • Math (double, double, double, float, char, int)
  • ...

So, in our example of averages, just create two constructor functions, one that receives two grades and the other that receives three grades:

#include <iostream>
using namespace std;

class Math
{
    public:
        Math(double, double);
        Math(double, double, double);
};

Math::Math(double g1, double g2)
{
    cout<<"Average: "<<(g1+g2)/2<<endl;
}

Math::Math(double g1, double g2, double g3)
{
    cout<<"Average: "<<(g1+g2+g3)/3<<endl;
}


int main()
{
    Math BruceDickinson(10, 8);
    Math NeilPeart(10, 9, 10);

    return 0;
}

See how smart C++ is. When you created the BruceDickinson object, you only passed two arguments, and the object invoked the constructor function that only works with two numbers.

When he created the ana object, he called the other constructor function, the one that works with three values.

That is, C++ calls the correct constructor!
This is the constructor overloading.

Now if you have two constructors with the same parameter list, then there is no way for C++ to guess what function you are trying to invoke, okay?

We will learn a little more about overload when we study a super special class, the string, which does crazy things and wonders with overloading.

Function Overloading: Different Parameters and Arguments

In this tutorial from our C++ e-book, we will learn what function overloading is, what it is for, and how to use this important programming technique.

Parameter and Arguments Sizes in C++ Functions

In the Default Arguments tutorial, we saw that you can send a variety of arguments to a function as long as it is using reference parameters.

For example, the code below is from a function that calculates an arithmetic average:
#include <iostream>
using namespace std;

float average(float a, float b, float c, float d = 0.0)
{
    return (a+b+c+d)/4;
}

int main()
{
    cout<<"Average of 3 numbers: "<<average(10, 9, 7)<<endl;
    cout<<"Average of 4 numbers: "<<average(10, 9, 7, 6)<<endl;

    return 0;
}
It can take 3 or 4 arguments. If you submit only 3, the 4 argument is the default, with a value of 0.
However, note an error.

Even if we only send 3 arguments, the arithmetic average is calculated as if there were 4 notes.

It would be interesting if, if I submitted 3 arguments, it would return:
(a + b + c) / 3

And if I sent 4 arguments, it would return:
(a + b + c + d) / 4

And this is possible with overloading functions.

C++ Function Overloading

Overloading is the technique that allows us to have functions with the same name as long as their parameters are different, in some way.

Here's what the 3 and for grade average program looks like:
#include <iostream>
using namespace std;

float average(float a, float b, float c)
{
    return (a+b+c)/3;
}

float average(float a, float b, float c, float d)
{
    return (a+b+c+d)/4;
}

int main()
{
    cout<<"Average of 3 numbers: "<<average(10, 9, 7)<<endl;
    cout<<"Average of 4 numbers: "<<average(10, 9, 7, 6)<<endl;

    return 0;
}
Note that we invoke the average() function, the only difference is that in the first call we pass 3 arguments, and in the second call of the function we pass 4 arguments.

Because C++ is naughty and smart, it knows which function to run correctly.

It is so clever that even if there are the same number of parameters / arguments, it can differentiate through the type of data we are using.

Look:
#include <iostream>
using namespace std;

double average(double a, double b, double c)
{
    cout<<"Average of 3 doubles   : ";
    return (a+b+c)/3;
}

int average(int a, int b, int c)
{
    cout<<"Average of 3 integers  : ";
    return (a+b+c)/3;
}

int main()
{
    cout<<average(10.0, 9.0, 7.0)<<endl;
    cout<<average(10, 9, 7)<<endl;

    return 0;
}
When we pass double type variables, it calls average(double, double, double)
When we pass int variables, it calls average(int, int, int)

C++ can differentiate because the signatures of each function are different (either in the number of parameters or the type that will work).

In fact, even if the functions have the same name, the same number of parameters, and the same data types, we can overload functions as long as the order of the parameters is different:
#include <iostream>
using namespace std;

void func(int a, double b)
{
    cout<<"First is int    : "<<a<<endl;
    cout<<"Second is double: "<<b<<endl;
}

void func(double b, int a)
{
    cout<<"First is double : "<<b<<endl;
    cout<<"Second is int   : "<<a<<endl;
}

int main()
{
    func(1, 2.5);
    cout<<endl;
    func(2.5, 1);

    return 0;
}
In the example we have: func (int, double)
Also: func (double, int)

Simply signature from one function to another is different so we can use overload where signature is a set: function name, data type, data number and order of information.

For good programming practices, you should use function overloading whenever you need to use functions with the same purpose and logic, but for different number and / or types and / or order of data.