13.5 — Overloading operators using member functions

In lesson 13.2 -- Overloading the arithmetic operators using friend functions, you learned how to overload the arithmetic operators using friend functions. You also learned you can overload operators as normal functions. Many operators can be overloaded in a different way: as a member function.

Overloading operators using a member function is very similar to overloading operators using a friend function. When overloading an operator using a member function:

  • The overloaded operator must be added as a member function of the left operand.
  • The left operand becomes the implicit *this object
  • All other operands become function parameters.

As a reminder, here’s how we overloaded operator+ using a friend function:

Converting a friend overloaded operator to a member overloaded operator is easy:

  1. The overloaded operator is defined as a member instead of a friend (Cents::operator+ instead of friend operator+)
  2. The left parameter is removed, because that parameter now becomes the implicit *this object.
  3. Inside the function body, all references to the left parameter can be removed (e.g. cents.m_cents becomes m_cents, which implicitly references the *this object).

Now, the same operator overloaded using the member function method:

Note that the usage of the operator does not change (in both cases, cents1 + 2), we’ve simply defined the function differently. Our two-parameter friend function becomes a one-parameter member function, with the leftmost parameter in the friend version (cents) becoming the implicit *this parameter in the member function version.

Let’s take a closer look at how the expression cents1 + 2 evaluates.

In the friend function version, the expression cents1 + 2 becomes function call operator+(cents1, 2). Note that there are two function parameters. This is straightforward.

In the member function version, the expression cents1 + 2 becomes function call cents1.operator+(2). Note that there is now only one explicit function parameter, and cents1 has become an object prefix. However, in lesson 11.10 -- The hidden “this” pointer, we mentioned that the compiler implicitly converts an object prefix into a hidden leftmost parameter named *this. So in actuality, cents1.operator+(2) becomes operator+(&cents1, 2), which is almost identical to the friend version.

Both cases produce the same result, just in slightly different ways.

So if we can overload an operator as a friend or a member, which should we use? In order to answer that question, there’s a few more things you’ll need to know.

Not everything can be overloaded as a friend function

The assignment (=), subscript ([]), function call (()), and member selection (->) operators must be overloaded as member functions, because the language requires them to be.

Not everything can be overloaded as a member function

In lesson 13.4 -- Overloading the I/O operators, we overloaded operator<< for our Point class using the friend function method. Here’s a reminder of how we did that:

However, we are not able to overload operator<< as a member function. Why not? Because the overloaded operator must be added as a member of the left operand. In this case, the left operand is an object of type std::ostream. std::ostream is fixed as part of the standard library. We can’t modify the class declaration to add the overload as a member function of std::ostream.

This necessitates that operator<< be overloaded as a normal function (preferred) or a friend.

Similarly, although we can overload operator+(Cents, int) as a member function (as we did above), we can’t overload operator+(int, Cents) as a member function, because int isn’t a class we can add members to.

Typically, we won’t be able to use a member overload if the left operand is either not a class (e.g. int), or it is a class that we can’t modify (e.g. std::ostream).

When to use a normal, friend, or member function overload

In most cases, the language leaves it up to you to determine whether you want to use the normal/friend or member function version of the overload. However, one of the two is usually a better choice than the other.

When dealing with binary operators that don’t modify the left operand (e.g. operator+), the normal or friend function version is typically preferred, because it works for all parameter types (even when the left operand isn’t a class object, or is a class that is not modifiable). The normal or friend function version has the added benefit of “symmetry”, as all operands become explicit parameters (instead of the left operand becoming *this and the right operand becoming an explicit parameter).

When dealing with binary operators that do modify the left operand (e.g. operator+=), the member function version is typically preferred. In these cases, the leftmost operand will always be a class type, and having the object being modified become the one pointed to by *this is natural. Because the rightmost operand becomes an explicit parameter, there’s no confusion over who is getting modified and who is getting evaluated.

Unary operators are usually overloaded as member functions as well, since the member version has no parameters.

The following rules of thumb can help you determine which form is best for a given situation:

  • If you’re overloading assignment (=), subscript ([]), function call (()), or member selection (->), do so as a member function.
  • If you’re overloading a unary operator, do so as a member function.
  • If you’re overloading a binary operator that does not modify its left operand (e.g. operator+), do so as a normal function (preferred) or friend function.
  • If you’re overloading a binary operator that modifies its left operand, but you can’t modify the definition of the left operand (e.g. operator<<, which has a left operand of type ostream), do so as a normal function (preferred) or friend function.
  • If you’re overloading a binary operator that modifies its left operand (e.g. operator+=), and you can modify the definition of the left operand, do so as a member function.

13.6 -- Overloading unary operators +, -, and !
13.4 -- Overloading the I/O operators

70 comments to 13.5 — Overloading operators using member functions

  • Gamer_to_be

    >>If you’re overloading a binary operator that modifies its left operand, but you can’t modify the definition of the left operand (e.g. operator<<, which has a left operand of type ostream), do so as a normal function (preferred) or friend function.

    Would you please explain how in operator<< or operator>>, their lest operands are modified? I mean we output something on screen and standard output(std::cout) is not changed! or we get value from input and modify for example the private members of a class not standard input (std::cin). How come this change is possible if they are modified as leftmost operands?

    • nascardriver

      `std::cout` don't immediately print or read. They store the output/input in a buffer that is later printed or read from. When you print/read, that buffer gets modified. You can also cause changes of the stream's flags, eg. when you input something invalid and `std::cin` enters its failed state.

  • Overload the Plus and Minus operator for Point class which has two data members x and y of type int. In main then make the objects of class and add and subtract using + and – operator.

    • PLease give a solution in a programe

    • Tom

  • Nikkie

    Hey, I'm a little confused about how you would implement the overloaded operator in the normal way. I completely understand the friend way, but how would you do it in the normal way?

    Friend way

    member function way

    • nascardriver

  • Ella

    What exactly is happening when we execute code Z = X + Y in operator overloaded
    function? Can you explain this for me...

  • David

    Hello,I still don't understand the meaning "The overloaded operator must be added as a member function of the left operand."
    what is that meaning "of the left operand"?
    Can you explain it in a simple way ?
    Thanks for replying

    • nascardriver

      where `a` is of type `A` and `b` is of type `B`.
      `a` is the left operand, `b` is the right operand. `operator+` must be overloaded in class `A` for the above statement to work.

      • David

        So you mean the return type for the operator+() should be the same as the type of the left operand.
        Does it correct?

        • nascardriver

          The `operator+` function must be a member of `A`. The return type doesn't matter.

  • Ged

    Question number 1

    Why does this code compile. Shouldn't there be a compile error for too many operator+ functions with the same parameter?

    • nascardriver

      Both functions can be defined, because they're different (member vs non-member), and both can be called

      When you do `cents1 + 2`, both functions are considered, but the member function wins. I can't tell you why the member function wins, maybe someone else can help.

  • Sekhar

    Hi Alex,  
    Is that OK to state that "Objects that belong to libraries should be used only with the friend/normal functions like iostream objects where the left operand is modified and returned". If the statement holds good I think it can be added as a rule of thumb.

    Thanks in advance,

    • Alex

      Yes, there's no other alternative. You can't overload them as members.

      • sekhar

        Thanks Alex.Just want to mention that it's better to explicitly add the statement "If you’re overloading a binary operator that modifies its left operand (e.g. operator<<, operator >>) that belongs to standard library do so as a friend function." to rule of thumb that you have mentioned as part of last paragraph.

  • Arno Adam

    Just a question if I understood the mechanics correctly: These past few chapters I was wondering whether operator overloading would cause memory leaks, because a new object is created every time an overloaded operator is used, correct? So I thought these new objects would continue to exist in memory alongside the original objects. But then I realized that the newly created object usually only has expression scope, because it's an r-value, right? Unless we assign it to something, like this:

    • Hi Arno!

      > a new object is created every time an overloaded operator is used
      Only some operator create copies (eg. the binary + and - operators). Others don't (eg. insertion, extraction, +=, -=).
      Those which create copies don't behave different than regular functions (Which also don't leak).
      Memory leaks only occur when you're dynamically allocating memory and not freeing it.

  • "Because the overloaded operator must be added as a member of the left operand"                      

    We didn't need to modify the class std::ostream if we overload << operator by friend function.  
    However, if we want to overload << operator by member function, why do we have to modify the class std::ostream(which make it impossible)?

  • Adrian

    I need some help sead

    "Similarly, although we can overload operator+(Cents, int) as a member function (as we did above), we can’t overload operator+(int, Cents) as a member function, because int isn’t a class we can add members to."

    But if i create an operator+(int, Cents) it works..

    • Alex

      You didn't create operator+(int, Cents), you created Cents::operator+(Cents), which adds two Cents and returns an int.

      Your code in main calls the (Cents + int) version, not the (int + Cents) version you thought you'd implemented.


    Rules of thumb to determine which form is best are to the point! Very good advice.

    By the way, regarding the following sentence "However, we are not able to overloaded operator<< as a member function.", "overloaded" could be replaced by "overload"?

  • Omri

    Right, thanks.
    Accordingly, perhaps , depending on compiler, we are not actually  overloading an exiting function when we create our user defined operatorOPR(...) function , although it may be helpful to think of the process in these terms.
    Thank you again.

  • Omri

    Thank you for the clarification.
    Is there a "straight forward" reason why build-in operators must be called using the "standard way" only?
    Knowing a reason may some times assist in memorising a rule...

    • Alex

      My best guess is because the compiler is free to not treat a built-in operator as a function at all -- it can just inline the resulting code, so there's no function with that name to even call.

  • omri

    Thank you for the reply.
    Is it correct to say the following:
    Overloaded versions of operatorOPR(...) functions can be created by the user and subsequently called using "x OPR y" format or more generally OPR format as suitable.
    Executing OPR by calling operatorOPR(...) function (built in version or overloaded version) is never allowed.
    Did I get this correct?
    If yes, its a wonder why this restriction is necessary...

    • Alex

      For user-defined overloads of operators, you can call them via the operator name (e.g. operator+(x, y)) or via the standard way (x + y). For build-in operators, you must use the standard way.

  • Omri

    Hello Alex,
    I understand that n+m implicitly stands for operator+(n,m). If n and m are integers (short, double etc.) an appropriate operator+(...) function is readily available and the operation is executed with a correct result returned. If n and/or m are user defined types an appropriate over loading of the operator+(...) function needs to be introduced by the user so that the
    "+" operation will function as the user wishes when used with his "user introduced type"...
    I tried to test the assumption that a function operator+(int x, int y) is indeed implicitly available and instead of writing:
    int x=5, y=10, z; z=x+y;
    I wrote:
    int x=5, y=10, z; z=operator+(x,y);
    The later did not compile.
    Can you clarify?

  • dazedbrain

    So if we can overload an operator as a friend or a member, which should use use?

    thx for the awesome tutorials!

  • nelson

    using friend function first argument is taken as const. but using memeber function why not const is taken?

    Note: i am using chain of operators

    using friend function operator overloading required const why?

    using member function operator overloading works even const is neglected why?

    • Alex

      You can't pass a temporary (anonymous) result to a function by non-const reference, so in the member function version where the temporary result is being passed in as a parameter to the function, it needs to be const.

      But you can call a non-const member function on a temporary result. So in the member function case, the const isn't needed. Though, this member function version of operator+ should really be const anyway, since it doesn't actually modify the class.

  • vaibhav

    alex can u debug this program plz

    /*wap in oop which overload binary '+' operator using member function*/
    class binary
    float x;
    float y;
    void collect()
    cout<<"\n\tenter value for addition";
    binary operator+(binarya,binaryb);
    void display();
    binary binary::operator+(binary B)
    binary temp;
    void binary::display()
    void main()
    binary B1,B2,B3;

    • Alex

      This line of your class definition doesn't match your member function implementation:

      You probably meant:

  • Vasant Prabhu

    Hi, I expected my code to return 12. But its giving me 5 as result.
    Not sure why this is happening.

    • Alex

      Your += operator is incorrect. += should modify the implicit object and then return that. Instead, you're creating a new Cents object and returning that.

      So when you do c1+=7, operator c1.operator+=(7) is returning a new Cents with the value 12 that is being discarded.

      Try this instead:

  • mrK

    hey, when i used ubuntu 14.04 to run that code, some errors make me confused "error: expected initializer before 'operator'". ???

  • Josh W

    I'm really starting to get the Point!

    I've been following these tutorials for a few days now and am learning a lot more than I've learned anywhere else. I took a programming class in HS (it taught VB.NET) and I realize now that the teacher didn't know anything about programming (we never talked about Object Oriented Programming for starters). Even so, I've been teaching myself to program in VB since then (about 8 years now) and learned quite a bit but came to a point where I decided I needed to try out C++ and find out why it's all the rage with the kids. Every tutorial I turned to started out expecting me to already be an expert or quickly went there. This is the only tutorial I've found that has given me genuine instruction in C++ that has given me the confidence to tackle my own projects in this new (to me) language!

  • Bro, there you have given link for section 9.6 , you missed 9.5 :-)

  • BlueTooth4269

    How would we overload the + operator for adding two Cents objects together as a member function?
    Is it even possible/recommended?

    • Alex

      It's possible -- you'd do it the same way as in the Cents + int case above, but with the function taking a Cents parameter instead of an int.

      However, it's recommended to use the friend version, as it's both more intuitive, and more flexible (you can implement int + Cents as a friend, but not as a member, since the left operand must be a class type in the member version, and int isn't).

  • Rahul

    "Remember that when C++ sees the function prototype Cents Cents::operator-();, the compiler internally converts this to Cents operator-(const Cents *this), which you will note is almost identical to our friend version Cents operator-(const Cents &cCents)!"

    Here, function prototype is Cents operator-();
    And if you mean to say its Cents Cents::operator-(); - which is defined outside outside the class, then the compiler would internally convert it to Cents Cents::operator-(const Cents *this) as it is a member function.

    Please clarify how compiler internally converts and links prototype and definition.

  • Arun Mathew Iype

    What is the reason that the operator= should always be a member function? Can this not be done using a friend function too?

    • Alex

      C++ requires operator= to be a member function. I'm guessing that this is because C++ will auto-generate one for you if you don't define one. If you were able to define one outside the class, the compiler wouldn't know whether to call the auto-generated one, or the one you wrote outside the class.

  • Vishnu

    Why Operator is not able to modify the private values when overloaded as function 1(defined below) ?

    • Alex

      Function 1 is correct. Consider your code:

      This takes object o1 and adds 10, which calls abc::operator+(int), which then returns the new object. However, your code does not do anything with this object, so it is discarded.

      You probably intended to do this:

      That way, the return value of o1 + 10 is assigned back to o1.

      Function 2 is logically incorrect. operator+ should not modify the object being called (operator += should).

  • Joseph

    Regarding the following statement:

    "However, when dealing with operands that modify the class itself (eg. operators =, +=, -=, ++, --, etc…) the member function method is typically used because C++ programmers are used to writing member functions (such as access functions) to modify private member variables."

    Would it be correct to say that C++ programmers mainly use friend functions to set and modify private member variables, and member functions to get and compare private member variables?

    • Alex


      Member functions are generally preferred whenever access to private members are needed. Friend functions are typically used when a function needs access to private data but a member function can't be used (e.g. a member of one class needs access to the private data of another class). Like many things, there are exceptions. One exception is for binary operator overloads that don't modify the left operand.

  • Priyali

    Hi Alex,

    I tried overloading binary addition (+) operator using a member function as shown below.


    using namespace std;

    class Cents
    int m_nCents;

    Cents(int nCents = 0) { m_nCents = nCents; }

    // Overload for Cents + Cents
    Cents operator+(const Cents &cTemp);

    int GetCents() { return m_nCents; }

    // note: this function is a member function!
    Cents Cents::operator+(const Cents &cTemp)
    return Cents(m_nCents + cTemp.m_nCents);

    int main()
    Cents cAdd;
    Cents c1(4);
    Cents c2(6);
    cAdd = c1 + c2;
    cout << "I have " << cAdd.GetCents() << " cents." << endl;

    return 0;


    The code is compiling without errors and giving me the desired output. As per my understanding, when I do c1+c2 , the call gets converted into Cents operator+(const Cents *this, const Cents &cTemp). How could "this pointer" which points to object c1 can access private member m_nCents of object c2(cTemp) even if its not a friend function. This is a bit confusing for me.

  • madhukar

    i want to know if i can have an overloaded unary operator. (don't know if that even makes sense.)
    i don't see how it is possible. The problem i was thinking about was-
    suppose obj1 and obj2 are two objects of the same class.
    i want to do:
    -M1; // the operator - function returns no value, just changes the values of the data members of M1
    M2=-M1 // the operator - function returns an object of the class.
    i was thinking of using both member function and friend function together would allow me to do this, haven't tried it yet though.

    • madhukar

      also, when operator - is called in
      data members of M1 remain unchanged.

      PS: im not trolling, was really wondering if its possible :S

      • Alex

        Yes, you can have an overloaded unary operator.

        If you do M2 = -M1, the unary operator- will be applied to M1 (with the result being returned by value, so that M1 isn't modified), and then the result will be assigned to M2.

        We will look at this in more detail shortly.

  • Tom

    Thanks Alex, this is starting to make cents. ;)

Leave a Comment

Put all code inside code tags: [code]your code here[/code]