Language Selector

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

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

  • chandu


    In the following code i want to negate the x, but i have two private members x & y in my class. i want to get the result of x negative how it is possible with code, or else o.w i want to negate the both the x & y members how it is possible.

    any one can explain these.


    class data
          int x;
          int y;
                 data(int x, int y)
                          this->x = x;
                          this->y = y;
                 int get_datax(void)
                     return x;
                 int get_datay(void)
                     return y;
                 friend data operator - (data &obj);

    data operator - (data &obj)
        return -(obj.x);

    int main()
        data obj1(10, 20);
        data obj2 = -obj1;
        cout << obj2.get_datax() <<endl;
        cout << obj2.get_datay() <<endl;

  • Niladri Patra

    Hi, I was trying to do operator overloading for vector algebra.

    Here are my codes (CVector.h, CVector.cpp and main.cpp; mostly copied from Internet). When I complile by (g++ main.cpp CVector.cpp CVector.h), they produce lots of error. I am new in C++. Please have a look.


    #ifndef _CVECTOR_ // Check if C Vector is defined
    #define _CVECTOR_ // the next time CVector will be define
    #define ZEROVECTOR CVector()
    class  CVector
    {       // Private
    float x,y,z,w; // Order list of 4 elements |x|y|z|w|
    static char sBuffer[38];               // static buffer to hold the string of given vector
    char* toString();                              // Return sBuffer with (x,y,z,w) values in it
    CVector (void);                                // zero Vector Constructor
    CVector (float,float,float);   // Constructor
    CVector (CVector&);                    // Copy Vector Constructor
    ~CVector();                                    // Destructor
    CVector  operator+(CVector&);  // Addition
    CVector  operator-(CVector&);  // Subtraction
    float    dotProduct(CVector&);
    void  operator=(CVector&);             // Copy Vector
    int  operator==(CVector&);             // Comparison Vector
    CVector  operator*(CVector&);  // Cross Product
    CVector  operator*(float);             // Scalar Multiplication
    float length();                                // Magnitude
    void normalize();
    #endif // _CVECTOR_




    #include "CVector.h"
    #include <math.h>
    #include <stdio.h>

    CVector::CVector (float xi,float yi,float zi){  // Constructor
        w=1.0f; // normalize the vector
    CVector::CVector (CVector& a){   // Copy Vector Constructor
    CVector::~CVector(){}    // Destructor
    CVector  CVector::operator+(CVector& a){  // Addition
        return CVector(x +a.x,y +a.y,z +a.z);
    CVector  CVector::operator-(CVector& a){  // Subtraction
    return CVector(x -a.x,y -a.y,z -a.z);
    float    CVector::dotProduct(CVector& a){
        return x*a.x+y*a.y+z*a.z;
    char CVector::sBuffer[38];// definition outside class declaration
    char* CVector::toString(){// 8 bytes per float*4+5+1=38 bytes per vector
        return sBuffer;
    int  CVector::operator==(CVector& a){  // Comparison Vector
        return (x==a.x && y==a.y && z==a.z);

    CVector::CVector (void){
    void CVector::operator=(CVector& a){  // Copy Vector
    CVector  CVector::operator*(CVector& a){  // Cross Product
        return CVector(y*a.z-z*a.y,z*a.x-x*a.z,x*a.y-a.x*y);
    CVector CVector::operator*(float a){  // Scalar Multiplication
        return CVector(x*a,y*a,z*a);
    float CVector::length(){   // Magnitude
        return sqrt(x*x+y*y+z*z);
    void CVector::normalize()
        float len = length();
        x = x/len;
        y = y/len;
        z = z/len;



    #include "CVector.h"
    #include "CVector.h"
    #include <stdio.h>
    #include <string>

    #define TEST_NORMALIZE_ERROR -0x01
    #define TEST_SCALAR_ERROR -0x04
    #define TEST_SUBTRACTION_ERROR -0x08
    #define TEST_ADDITION_ERROR -0x10
    #define TEST_COPY_ERROR -0x20
    using namespace std;
    int main()
    CVector i,j,k;
    CVector a,b,c;
    i = CVector(5.0f,0.0f,0.0f);
    j = CVector(0.0f,6.0f,0.0f);
    printf("CVector Example\n");
    // Unit test.
    k = i*j;
    if(i.length() != 1.0f){
    cout << "Failed to Normileze i" << endl;
    if(j.length() != 1.0f){
    cout << "Failed to Normileze j" << endl;
    if(k.length() != 1.0f){
    cout << "Failed k Should be normalized" << endl;
    if(!(k == CVector(0.0f,0.0f,1.0f))){
    cout << "Failed Cross Product, k=i*j" << endl;
    cout << "Failed Scalar Multiplication or Cross Product" << endl;
    cout << "Failed to Substract" << endl;
    c = CVector(7.0f,2.0f,-4.0f);
    b = c;
    cout << "Failed to Copy Vector" << endl;
    return TEST_COPY_ERROR;
    c = CVector(7.0f,2.0f,-4.0f);
    cout << "Failed to Addition or Scalar Multiplication" << endl;
    printf("All test Pass. \n");


  • Mr D

    Hi Alex,

    Something is confusing me!:

    With overloading the "-" operator, you use:

    But with overloading the "!" op’, you use:

    But why isn’t it:


    • Alex

      Generally when we overload operators, we try and keep them as close to the “intent” of the original operator as possible. So while you could make operator- multiply each of the dimensions in your Point by 2, that would be rather confusing, because we wouldn’t expect operator- to do that.

      Now let’s consider how operator! (logical NOT) works with normal variables. For a normal boolean value, it returns true when the boolean is false (0), and false when the boolean is true (1). For an integer, it returns true when the integer is 0, and false otherwise. We could generalize this to say that operator! returns true whenever our input value is a zero/null value, and false otherwise.

      What’s the zero value for a Point? Point(0.0, 0.0, 0.0) is the closest thing. So for consistency, it makes sense that our operator! return true when the Point is the zero Point (0.0, 0.0, 0.0) and false otherwise.

      If operator! did return a Point, what values would you expect it to have if you gave it Point(1.0, 2.0, 3.0) as input?

  • Mr D

    Thanks for the explanation, i get it!

Leave a Comment




20 − 12 =

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