0

Can someone please explain, in beginner terms, how operator overloading works? I need to overload the "+" operator as a member function with chaining to an objects array. Ive read some things from google, and it seems to operates the same way as "+" does without being overloaded, so I'm really confused.

This is what I have so far for the declaration:

ALIST<t_type> & operator+(const t_type );

So I declared this inside my ALIST class in the public section. Is the "+" operator overloaded now, or is there more I need to do in this functions definition to make it overloaded?

Also, once it is finally overloaded, what can I now do with it? What was the point of overloading it?

Please explain in beginner terms please, thanks.

Mike
  • 479
  • 2
  • 7
  • 24
  • 2
    "Also, once it is finally overloaded, what can I now do with it? What was the point of overloading it?" Forget about everything else in the question and get on top of that crucial detail first. If you don't know whether or not overloading is useful to you, why bother implementing it? – David Heffernan May 22 '12 at 19:18
  • You'd have to actually define the operator besides just declaring it... – K-ballo May 22 '12 at 19:19
  • 1
    If you do not know what's the point of overloading the operator, what was the purpose of overloading it in the first place? – Sergey Kalinichenko May 22 '12 at 19:19
  • 1
    @DavidHeffernan Because Im working on something where I have to overload it. – Mike May 22 '12 at 19:24
  • 1
    @DavidHeffernan I didnt feel like explaining why I had to do it, I just wanted help trying to figure out how to do it. – Mike May 22 '12 at 19:25
  • 1
    Well, the answer to why you would overload it is to allow you to use the `+` operator on user defined types. You might not feel like explaining why, but doing so sure helps us to help you. – David Heffernan May 22 '12 at 19:25

5 Answers5

3

Here is an example for why.

Say you are implementing a class of special vectors. For instance a Color class. Colors are going to basically be vectors with 4 values, r,g,b,a.

Now we are writing a graphics engine and in our program we will often want to know what happens to a pixels when the light from two different sources act on a pixel we are evaulauting (as in a ray tracer). It would be convient for to define a + operator to evaulate what happens when the light from two different sources are added together.

If we didnt have an operator you might write in your code to add two Colors together:

Color newColor = Color(
    color1.r + color2.r, 
    color1.g + color2.g,
    color1.b + color2.b,
    color1.a + color2.a
);

Even worse, if you are working closely with the physics of the light you might find that colors dont add normally. They might for instance add according to some linear function e.g. f(a) = a^2 ... (light doesn't do this I don't think, its just a random example).

f(a) = a^2; f(b) = b^2
f(a + b) = ??
a = f(a)^.5; b = f(b)^.5
a + b = f(a)^.5 + f(b)^.5
f(a + b) = (f(a)^.5 + f(b)^.5)^2 *yada yada yada i'm terrible at math.

Which means our Color adding code now becomes

Color newColor = Color(
    pow(pow(color1.r, .5) + pow(color2.r, .5),2), 
    pow(pow(color1.g, .5) + pow(color2.g, .5),2),
    pow(pow(color1.b, .5) + pow(color2.b, .5),2),
    pow(pow(color1.a, .5) + pow(color2.a, .5),2), 
);

A pain to write out. But of course, If we take the Color class, and overwrite the add operator to do all of this for us, in our code we can just write

Color color = color1 + color2;

With this defined in out Color class definition

Color Color::operator+(const Color &rhs) const {
     return Color(
           pow(pow(this.r, .5) + pow(rhs.r, .5),2), 
           pow(pow(this.g, .5) + pow(rhs.g, .5),2),
           pow(pow(this.b, .5) + pow(rhs.b, .5),2),
           pow(pow(this.a, .5) + pow(rhs.a, .5),2)
     ); 
}

Since our special adding code is in only one place, you can optimize it far better, and the code in the rest of your program becomes much more readable.

That one way to looks at it at least. In the past, I have prefered functions like addLights(color1, color2) as this is easier to code, just as easy to read, and more readable since it is obvious it is not a traditional vector add. I bet you could go your entire career not overriding operators and I dont think you would not be missing out on much.

Mooing Duck
  • 56,371
  • 16
  • 89
  • 146
gbtimmon
  • 3,863
  • 1
  • 17
  • 31
  • Great example! I fixed some of the syntax that needed touchups. – Mooing Duck May 22 '12 at 20:29
  • @Mooing Duck, Thanks, I was worried about that. You could probably tell that c++ is not my first language. I dont use it much, and I dont know most of the syntax without looking it up. – gbtimmon May 23 '12 at 15:52
0

If you have a custom class and want to be able to "add" two instances of that class together the operator+ overload would allow you customize how two objects are "added" together.

You need to now implement the operator+ method in your .h or .cpp file.

Marcus Recck
  • 4,879
  • 2
  • 14
  • 26
0

So far you got a correct declaration, then you will need to implement it, i.e. fill in the body by adding the input parameter to an internally managed array, for instance.

When you have this on place you will be able to say mylist = mylist + mytype; instead of mylist.add(mytype) for instance. Not a big deal in this case, but if you are developing classes that should naturally work with standard operators like mathematical Matrices, Vectors, Complex Numbers etc, or if you override [] operator in your ALIST class it makes more sense.

Hakan Serce
  • 10,888
  • 3
  • 26
  • 43
0

By default, the operator symbols are designed to work with the built-in types (int, char, string, etc).

It wasn't possible for the creator of C++ to define how the operands should work for user defined types, so he implemented a system where you can overload them and define the behavior yourself in a way that makes sense in the context of that object.

You'd generally overload an operator like this:

in the class.h

class MyClass {
    int a;
    MyClass(int value) : a(value) {}
    MyClass MyClass::operator+(const MyClass&) const;
}

in the class.cpp

MyClass MyClass::operator+(const MyClass& other) const
{
    return MyClass(this->a+other.a);
}

which would return a new MyClass with the variable a set to the value of both MyClass's a's added together. Once this is done, you can do stuff like this:

MyClass first(2);
MyClass second(5);
MyClass last = first + second;
std::cout << last.a << std::endl; // prints 7, which is the result of 2+5

Without overloading operator+ on MyClass, adding two MyClass's together would be invalid.

Mooing Duck
  • 56,371
  • 16
  • 89
  • 146
Mike Corcoran
  • 12,622
  • 4
  • 31
  • 46
0

As mentioned, there must be an implementation. Merely prototyping an overload doesn't get the compiler to write the operation for you.

If you are a beginner (or at least, seeking an answer in "beginner terms"), operator overloading isn't necessarily the best idea to jump straight into using in important projects. There are some semantic questions involved...because + is a very abstract symbol that may mean many different things to people reading your code, while a more descriptive name could be better.

Notice that even the standard libraries don't offer things like appending via += to vectors, since they store elements that might be added together...or append the vectors...or add an element to the end...add nauseum [pun intended]. It's tricky to call one definition of "add" the most "right":

Why not overload operator+=() for std::vector?

(Note that since std::string does not store arbitrary mathematical types, it's less ambiguous.)

It can also be hard to search for where these operator methods are being called, because there is no unique name for your method to search for. To find the calls you will have to sift through + used in contexts for arithmetic and string classes, etc.

Beyond naming issues, I'll also mention that operator overloading ties your hands in terms of if you want to pass additional parameters later. What if you want to expand with a priority parameter each time you put something in the list? There are tricks for getting around it, such as maintaining the overloads as default implementations as well as having the parameterized methods. Or you could do what iostreams adopted for <iomanip>:

http://www.cplusplus.com/reference/iostream/manipulators/

But it just points to the idea that caution should be used before diving into operator overloading in your domain. Another subtlety to be aware of is the difference between overloading using a global "friend" function of your class, vs. making an overload that is a member. There's a discussion of that here...

Operator overloading : member function vs. non-member function?

One important point is that if you wanted to give meaning to the situation where a non-class (such as an integer) appears on the left hand side of an operation, there's no way to add methods to int. So you'd have to make it a global overload.

Community
  • 1
  • 1