The Three Basic RulesWhen it comes to operator overloading in C++, there are three basic rules you should follow. As with all such rules, there are indeed exceptions. Sometimes people have deviated from them and the outcome was not bad code, but such positive deviations are few and far between. At the very least, 99 out of 100 such deviations I have seen were unjustified. However, it might just as well have been 999 out of 1000. So you’d better stick to the following rules.
- Whenever the meaning of an operator is not obviously clear and undisputed, it should not be overloaded. Instead, provide a function with a well-chosen name.
Basically, the first and foremost rule for overloading operators, at its very heart, says: Don’t do it. That might seem strange, because there is a lot to be known about operator overloading and so a lot of article, book chapter, and other texts deal with all this. But despite this seemingly obvious evidence, there are only a surprisingly few cases where operator overloading is appropriate. The reason is that actually it is hard to understand the semantics behind the application of an operator unless the use of the operator in the application domain is well known and undisputed. Contrary to popular believe, this is hardly ever the case.
- Always stick to the operator’s well-known semantics.
C++ poses no limitations on the semantics of overloaded operators. Your compiler will happily accept code that implements the binary
+operator to change its right operand. However, the users of such an operator would never suspect the expression
a + bto subtract
b. Of course, this supposes that the semantics of the operator in the application domain is undisputed.
- Always provide all out of a set of related operations.
Operators are related to each other and to other operations. If your type supports
a + b, users will expect to be able to call
a += b, too. If it supports prefix increment
++a, they will expect
a++to work as well. If they can check whether
a < b, they will most certainly expect to also to be able to check whether
a > b. If they can copy-construct your type, they expect assignment to work as well.