Click here to Skip to main content
15,029,369 members
Please Sign up or sign in to vote.
4.71/5 (6 votes)
See more:
Why do we overload operators? Can an overloaded operator change its original meaning in so far that the * operator can be used for +?

Thanks in advance!
Updated 18-Jan-11 10:16am
Manfred Rudolf Bihy 18-Jan-11 16:39pm
I voted 5 for your question as it is a really interesting one that really deserves some consideration. Not everything that can be done should also be done, but if we're not prepared to ask the right questions we might fall victim to all kind of fallacies!
Espen Harlinn 19-Jan-11 9:33am
5+ Resulted in a rather nice and intersting "discussion"

Yes indeed - you can make most operators do anything you want, but please don't make a * into a + - it's a bad idea, unless you really intend to confuse you coworkers.

As a rule of thumb I think operator overloading shoul be used to provide logic that's semantically compatible whith the operator in question.

Now, here is a library that does not adhere to that "rule of thumb" Boost Spirit[^] is an excellent example of putting operator overloading to good use - redefining the operators to enable definition of grammars in c++, using a notation that closely adheres to EBNF. In my opinion this makes sense since grammars are usually specified in EBNF.

Espen Harlinn
Sergey Alexandrovich Kryukov 18-Jan-11 16:10pm
Same thing - a 5, but the use of brackets should be noted.
Manfred Rudolf Bihy 18-Jan-11 16:14pm
Sematically compatible, good point! 5+
See my answer I think we agree.
fjdiewornncalwe 18-Jan-11 16:47pm
+5... I can't help but think that "don't make a * into a +" deserves to have "because someone maintaining the code later will say '*%@#$%@' about what you did."
Espen Harlinn 18-Jan-11 16:54pm
Thanks Marcus
Emilio Garavaglia 19-Jan-11 2:48am
well ... boost spirit make a use of operators that has nothing to deal with the operator original meaning (and the same can be said about iostreams: << is "bit shift" after all!)

The reason why this is a "good use" while me -writing a non conventional use of an opertor- i'm doing "bad use" looks partigian.

It's like say "you do good use of operators if you're already famous otherwise you'll never be".

To me "good" and "bad use" simple means "combine coherently to for meaningful expressions or not".
Everything else is marketing, not science.
Espen Harlinn 19-Jan-11 5:32am
But it does come close to EBNF notation in C++, that quite a feat :)
Emilio Garavaglia 19-Jan-11 8:34am
EBNF is not C++!
So ... they are "good" because already famous (like EBNF is... hence "marketing") and because are consistent in themselves (they "combine in meaningful expressions"). Certainly not because they are algebraically the same as the built-in ones!
Espen Harlinn 19-Jan-11 8:42am
Have you tried it out? IMHO the "syntactic sugar" makes the code more "readable". Grammars tends to become rather complex beasts, so I consider anything that makes the code conform closer to the specification quite useful. Grammars tend to be specified in EBNF.
JF2015 19-Jan-11 2:50am
Good answer.
Espen Harlinn 19-Jan-11 5:30am
Thanks JF2015!
Emilio Garavaglia 19-Jan-11 8:56am
I think you are misunderstanding me.
My point is not "boost is bad because", or "no is good because".

Simply, in your post, first you say
"Usually operator overloading is used to provide logic that's semantically compatible whith the operator in question."
then you say
"Boost Spirit[^] is an excellent example".

To me, Boost is an excellent example of overloading, but not of "semantically compatible with the operator in question" (in spirit * doesn't "multiply" anything!)
It is the demonstration they such a compatibility is not a prerequisite (unlike many time tough to students! Boost couldn't even exist if certain "good practice" would always been taken into account!)
Espen Harlinn 19-Jan-11 9:11am
Yes, you are quite right. As a rule of thumb I think we should strive to adhere to create code that's "semantically compatible whith the operator in question", and then I try to show that this is only a rule of thumb - sometimes other considerations must be taken into account, and spirit is an excellent example.
Espen Harlinn 19-Jan-11 9:21am
I've update my answer, making my point more explissit :)
Operator overloading is nice, but you should understand basically it's just for the syntax candy.

Of course you can changes the meaning the way you ask. Probably every single C++ book shows at least a paragraph explaining why it's bad to foolish yourself in this way. Operators have much more important uses than that.

If you change the customary meaning of the operator, you should not forget that the bracket rules (operator precedence) are still governed by the operator itself, not its modified meaning.
Manfred Rudolf Bihy 18-Jan-11 16:11pm
Yep, agreed! 5+
Espen Harlinn 18-Jan-11 16:40pm
5+ (Now if we could alter operator precedence, we'd have a whole new playground for subtle tricks confusing the unwary, our coworkers, and friends)
Sergey Alexandrovich Kryukov 18-Jan-11 16:42pm
Yes, like a contest "Most obfuscated C++ code" -- would be intriguing.
Overloading an operator is a tricky subject. The good (or bad it really depends) part is you can overload all these operators:[^]

The problem is the benefit has to be greater than the confusion you can produce by doing this. If you decide to overload an operator and it significantly changes the usual semantic of that operator it has to be very well documented not only in the overloaded definition but also where it is used.
Since a change in the semantic of an operator can be quite obtrusive for the "normal" user it might be indicated to use it internally only.
But as I said before it really depends on the usefulness of it all.

My 2<samll>cts!

Hope this helps. If you have a concrete scenario in mind leave me a comment so we can discuss it.

Best regards,
Sergey Alexandrovich Kryukov 18-Jan-11 16:15pm
Hm. Very mature notes - my 5.
I would say operators becomes tricky when applied or returned references, use memory allocation, etc.
Manfred Rudolf Bihy 18-Jan-11 16:20pm
OMG! I didn't even think about that before (common sense maybe). Operators imposing side effects on the involved operands apart from the returned result. :shudders: :cringes:
Espen Harlinn 18-Jan-11 16:42pm
5+ Imagine the entries to a c++ obfuscation contest :)
Manfred Rudolf Bihy 18-Jan-11 16:45pm
Gives a whole new meaning to security by obscurity! :)
Sergey Alexandrovich Kryukov 18-Jan-11 21:18pm
You're joking, but I saw people (and even worked with some of them, not just one) who really tried to manually make the code or data obscured and argues it helps security.
Manfred Rudolf Bihy 19-Jan-11 12:13pm
You're right it was meant as a joke, but it's also sad and true that some people still think there is any "value" to that. That are the same folks that like to say: "I have a real simple but effective encryption algorithm and if I keep it secret no one will be able to break my code". Had some good laughs on that one before.
Sergey Alexandrovich Kryukov 19-Jan-11 19:11pm
Aha; I often hear arguments about having user's data in text form but not manually manipulated by the users themselves, because they would like to hack the data, and the company would be forced to take responsibility (because the code had a habit to crash without any diagnostics (effect of heroically blocking exceptions from propagation) on a slightest inconsistency in user's data).

One of such designers, passing their treasured legacy to me, explained the "security" algorithm he invented with unimaginable proud in his voice: he devised some stupid home-baked text format for user's data, it was then zipped, and then the resulting byte sequence was cyclically shifted byte-by-byte by some secret number of bytes. Very nice guy, by the way (unless you say he did anything wrong, of course).
An overloaded operator is just a "function", so you can do your functions to do whatever you want.

But overloaded operator retain their role in expression (they will retain their nature of being prefix, postfix or infix, as well as their precedence).

So wherever you can write
A operator*(const A& a, const A& b) 
{ return a+b; }

(if it is that what you mean with "turning it into a +" )
will always retain a "multiplicative behavior" respect to +:

a + b * c
will be evaluated as
a + (b*c)
and will never become

Even if you revert the semantics of * and +.
Espen Harlinn 19-Jan-11 9:03am
5+ correct - so very correct :)
Manfred Rudolf Bihy 19-Jan-11 12:07pm
This is actually a necessity. Changing operator precedence is a very tricky subject as it changes the way the AST (abstract syntax tree) is built. If we were able to change operator precedence it could be done in way that would break the parsers ability to identify expressions. I did some compiler building in my time and have run into a lot of problems with ambigous grammars that were easily resolved by introducing precedence (PREC) and associativity (ASSOC) definitions.
If these could be changed by the programmer the grammar could very easily be broken by doing stupid stuff.
This is one of the most comprehensive FAQs on this topic:[^]
Sergey Alexandrovich Kryukov 18-Jan-11 16:11pm
Pretty good reference - a 5, there are a lot more sources -- just Google (but use critical thinking)
Manfred Rudolf Bihy 18-Jan-11 16:14pm
Good link! 5+
Espen Harlinn 18-Jan-11 16:14pm
5+ A nice uncomplicated overview. The is one thing though:
22.Use common sense
How common is common sense? cout << "Hello, I'm feeling dizzy, it feels like the world is shifting" << endl;
Nish Nishant 18-Jan-11 16:17pm
Well the makers of C++ knew that common sense may not be all that common which is why they decided not to let programmers redefine operators on intrinsic types. A good thing totally! :-)
Espen Harlinn 18-Jan-11 16:26pm
Wise, yes, but it would have been great fun :)
int result = 1+2;
cout << result << endl;
program output:
Nish Nishant 18-Jan-11 16:27pm
Exactly :-)
fjdiewornncalwe 18-Jan-11 16:46pm
+5. Awesome
I overload operators for notational convenience for file/console output or making calculations, such as if I want to add to vectors or multiply matrices. You can overload * and many other operators, but you cannot change the # of inputs to the operator unfortunately. For instance [] cannot take multiple inputs for a matrix. Example: you must use A[1][2][3] instead of A[1,2,3].

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900