9.5 — Overloading unary operators +, -, and !

Overloading unary operators

Unlike the operators you’ve seen so far, the positive (+), negative (-) and logical not (!) operators all are unary operators, which means they only operate on one operand. Because none of these operators change their operands, we will be implementing them as friend functions. All three operands are implemented in an identical manner.

Let’s take a look at how we’d implement operator- on the Cents class we used in a previous example:

This should be extremely straightforward. Our overloaded negative operator (-) takes one parameter of type Cents, and returns a value of type Cents.

Here’s another example. The ! operator is often used as a shorthand method to test if something is set to the value zero. For example, the following example would only execute if nX were zero:

Similarly, we can overload the ! operator to work similarly for a user-defined class:

In this case, if our point has coordinates (0.0, 0.0, 0.0), the logical not operator will return true. Otherwise, it will return false. Thus, we can say:

which produces the result:

cPoint was set at the origin.
9.6 -- Overloading operators using member functions
9.4 -- Overloading the comparison operators

12 comments to 9.5 — Overloading unary operators +, -, and !

  • gans

    Hi Alex,

    In the beginning of the section, u have mentioed that friend can be used if the operands are not getting modified. However in this section you re using friend with unary opearotors which changes the operands. please explain.:)

    • integral

      Hi gans,

      He is not actually modifying the operand.
      The following line is a function call to create a new Point object
      Point(-cPoint.m_dX, -cPoint.m_dY, -cPoint.m_dZ)

      My understanding is that when the above function call is made the operator- function copies the each data member of cPoint, decreases it by one and passes this new value using "pass by value" to the Point constructor to create a new object of type Point which is then returned by the operator- function.

      // Convert a Point into it's negative equivalent
      Point operator- (const Point &cPoint)
      return Point(-cPoint.m_dX, -cPoint.m_dY, -cPoint.m_dZ);

      • coderX

        Hi integral,

        Point(-cPoint.m_dX, -cPoint.m_dY, -cPoint.m_dZ)
        does not decreases the value by one. It just negate the X,Y and Z cordinate value.

  • Kavitha


    I didn't understand why the object reference is passed as constant.Is there any specific reason behind it?Can you please elaborate.Thank you!

    Point operator- (const Point &cPoint)   
        return Point(-cPoint.m_dX, -cPoint.m_dY, -cPoint.m_dZ);   
    • Making cPoint const means that this function will work with both non-const and const Points. If cPoint were not const, then we would not be able to call it with a const Point because the compiler could not guarantee we would not try to change the value.

      In general, it's a always good idea to pass your references as const if you are not going to modify the object being referenced. This not only makes it so your function can work with const objects, it also helps ensure you don't inadvertently change the object, and serves as notification to anyone calling the function that the object being passed in will not be changed.

  • davidv
    if (nX)
        // do something

    should be

    if (!nX)
        // do something

    [ Fixed! Thank you. -Alex ]

  • Shaun

    Is there an operator I can use to overload the usual if() effect? E.g.,

    if (cPoint)
        cout << "cPoint is not at the origin." << endl;
        cout << "cPoint is at the origin." << endl;

    What would happen in this case? Would C++ call the ! operator and reverse the result? Or is there another way to provide a boolean operator?

    • I think you could do this via overloading typecasts. If you provide an overloaded boolean conversion operator for your point, then I think the above example would work. This is covered in lesson 9.10.

      However, personally I wouldn't recommend implementing it this way. The conversion from point to boolean isn't very intuitive. I think this is better implemented as a member function that returns a boolean result -- in this way, your code will be more self-documenting. eg:

      if (cPoint.IsOrigin())
          // etc
      • Adrian

        If I may add a remark: In my opinion Shaun is quite right … If you decide to have an operator!() to check whether a point is non-zero, then it might also be intuitive to have a means of checking the opposite condition.

        But considering the technical point of view, the usual way to do this would be a typecast to void *, even if this looks strange at first sight. This is because a pointer-to-void is perfectly legal as the expression of an if-statement, but it will not be automatically converted to many other things. As a consequence, typing errors are less likely to bite you, because they will produce compiler errors more often.

        A typical example are all std::ios objects, which provide a typecasting operator void *() (and the opposite operator!()) in order to check their state. Consider the stereotypical example, assuming n is an int:

        if (std::cin >> n) { /* n could be read, everything is fine */ }
        if (std::cin << n) { /* this is apparently a typo */ }

        If std::cin had a conversion operator to bool, the second line would in fact compile, but it would certainly not do what you intended.

        • Gurjinder

          There is a problem with the typecast to void* approach. Because the object can be typecast to a void*, delete operator can be invoked on the object now (though the object is on stack):

          Point cPoint;
          delete cPoint;

          This can be disastrous!!!

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">