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

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

  • Shaun

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

    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:

      • 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 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):

          This can be disastrous!!!

  • davidv

    should be

    [ Fixed! Thank you. -Alex ]

  • 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!

    • 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.

  • 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.

  • Janez

    Is it ok to compare floating-point values like that (dX == 0.0)?

  • C++ newbie

    Hey there, I just want to say that this chapter has been an excellent read, and the tutorial so far has been a blast.  I came in with no prior experience and now I would consider myself sufficient in the language that I could write that I know it on my CV.  Thanks again for setting this website up.

Leave a Comment




5 × 5 =

Put C++ code inside [code][/code] tags to use the syntax highlighter