Channels ▼

Andrew Koenig

Dr. Dobb's Bloggers

Out of Sorts: How Not To Overload Operators

June 29, 2011

By now, I suspect you're getting tired of reading about order relations, so I'm going to go back to my original article about teaching C++ and look at the next topic: overloading operators as member functions in ways that behave differently from their built-in counterparts.

Here is a typical example:

             class Thing {
         // …
         Thing operator+(const Thing&) const;
         // …

The programmer is defining a class named Thing that, among other members, has one named operator+. This member is called in a context such as

    Thing t1, t2;

     // …

     … t1 + t2 …

in which the subexpression t1+t2 is a shorthand way of writing t1.operator+(t2).

People who write code such as this argue that "it is more object-oriented." Often they have used Java, in which all functions are members of classes, so this style is more familiar. Sometimes they merely want to explain member functions before they explain nonmember functions. Whatever the reason, this style of coding has a serious problem that comes from a discrepancy between readers' expectations of how overloaded operators behave and how they actually behave.

When we see an expression such as t1+t2, we expect that t1 and t2 will have similar constraints. We do not necessarily expect that t1+t2 will have the same value as t2+t1 (because we are used to seeing + for string concatenation, for example), but we expect that if t1+t2 compiles, then t2+t1 will do so as well. Making operator+ a member thwarts this expectation, because the left side of a member function call is not subject to the same conversion rules as the right side.

For example, suppose we add a constructor Thing(int) to our class. This constructor allows us to convert an int to a Thing, so if t1 is a Thing, we can write t1+1 as an expression. What we cannot do, however, is write 1+t1, because the left side of a member-function call is not automatically converted.

Notice that this expectation comes both from the use of an overloaded operator and from the particular choice of operator. It is much more surprising for 1+t1 to fail than for 1+=t1 to fail, because we do not expect the left operand of += to be converted. Similarly, if we had named our member add instead of operator+, we would not expect 1.add(t1) to work even though t1.add(1) does so (and even if we did not notice that 1. is a floating-point literal, which means that the "." is not part of a member-function call at all). In both cases, the usual usage of these members (operator+= and add, respectively) creates expectations that our code follows. These expectations are different from those created by overloading "ordinary" operators such as +.

It is possible to make a case that symmetric operations such as order relations should never be member functions. That's a tricky pedagogical matter, because it means that in order to show students how to define such operations, one must first either explain friend functions or tell the students to make data members public when they should really be private. However, because C++ uses the same syntactic rules for overloaded operators as it uses for the built-in versions of those operators, it is unwise to teach beginners to define overloaded operators that thwart the expectations that readers have developed from the built-in versions of those operators.

Related Reading

More Insights

Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.