At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga.
Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus.
Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.
So, this article explains, in general, how Operator Overloading works: http://en.wikipedia.org/wiki/Operator_overloading
In a nutshell, the practice of Operator Overloading essentially allows you to take basic operators, such as "+", and give them different behaviors based on what the operands are.
So, for example, let's say you have to integers. intA and intB. The + operator makes sense for these two operators. It's whatever the sum of the two integers are.
But, what if you have two arbitrary classes: classA and classB. What happens when you try to do this: classA + classB
It doesn't make sense by default because they are not integers or strings. However, when C++ sees that, it will check for an overloaded version of that operator. If it finds such an overloaded version, it will run that instead of a normal add operation.
Anyway, I hope that's a good explanation. I've never had cause to use it extensively. If you have any further questions, just ask. :)
An overloaded operator functions in much the same way as an overridden virtual function. They have defined signatures (there are multiple valid versions for each operator) and are called just like a function when the operator is used (as farmdawgnation described). In addition to the normal arithmetic operators (+-*/), you can also overload the assignment operator = (vital for concepts such as smart pointers) and compound assignment operators, modulo (%), pre- and post increment and decrement (i--, --i, i++, ++i), comparison operators, logical operators, dereferencing operators, stream insertion and extraction operators (<<, >>) and pretty much anything else you can think of. new and delete are also operators that can be overloaded, so you can implement custom memory allocation for each class if you like.
Operator overloading is extremely powerful and can make your code much easier to understand. Imagine a vector class in a math library - without overloaded operators, you'd have to implement add or subtract as functions, so a simple operation like adding the difference between vectors a and b to vector c and multiplying the result by d, can turn into a pretty ugly line of code:
Vector result = d.Multiply(c.Add( a.Subtract(b) ));
At first glance, it's difficult to understand what this code does. Now compare to the version with overloaded operators:
Vector result = d * ( c + (a-b) );
Much better, isn't it?
It's up to you what the operators do, but I highly recommend sticking to common sense and established conventions. Always write your code as if someone else was going to use it - even if nobody else does, chances are you'll end up looking at it again six months after you wrote it and won't remember what it did, so it's in effect as if someone else is trying to use it ;)
Some software I've seen does strange things, for example decide to override the ^ operator in a string class to do string concatenation. ^ is the XOR operator, so having it do string concatention makes not a bit of sense and is fairly unintuitive - if 0xFFFF ^ 0x1111 = 0xEEEE, then why is "Hello" ^ "World" = "Hello World"?