Youmair
Youmair

Reputation: 47

Operator Functions as Member Functions and Nonmember Functions

I am very confuse in getting the idea of operator overloading as a member and non member function.

What do we actually mean, when we overload operator as a non-member function and similarly what do we mean when we overload operator as a member functions. Although I know that the non-member functions are the friend functions.

Upvotes: 0

Views: 863

Answers (4)

robert
robert

Reputation: 34398

Most operators should be defined as members.

class MyClass
{
...
public:
    const MyClass& operator+=(const MyClass&);
};

Bit this is identical in behavior to the following:

class MyClass {...};
const MyClass& operator+=(const MyClass&, const MyClass&);

The implied this in the first example is analagous to the first parameter to the second example. If the second example needs access to the internal state of MyClass, it needs to be friended.

class MyClass
{
    friend const MyClass& operator+=(const MyClass&, const MyClass&);
};
const MyClass& operator+=(const MyClass&, const MyClass&);

The prototypical exception to this is operator<< on std::ostream.

std::ostream& operator<<(std::ostream&, const MyClass&);

This is logically a member of your MyClass, but because of the ordering of the parameters it would have to be a non-member of both classes or a member of std::ostream. Because you can't add members to std::ostream, this must be defined as a non-member.

Upvotes: 0

kamilk
kamilk

Reputation: 4039

A small example: (I haven't tried compiling this code but I hope it works)

class MyClass
{
public:
    MyClass operator+(const MyClass& other) const; //member operator declaration

    friend MyClass operator-(const MyClass& first, const MyClass& second); //non-member operator friend declaration
private:
    int _a;
}

//member operator definition
MyClass MyClass::operator+(const MyClass& other) const
{
    MyClass result;
    result._a = _a + other._a;
    return result;
}

//non-member operator definition
MyClass MyClass::operator-(const MyClass& first, const MyClass& second)
{
    MyClass result;
    result._a = first._a - second._a;
    return result;
}

Mind the differences: in the member operator definition I don't specify anything before the first _a after "=" - this->_a is assumed.

The member operator functions can be used only if an instance of your class is the first argument of the operator. If, for example you wanted to do something like 2 + myClassObject, you would need to override the non-member operator MyClass MyClass::operator+(int first, const MyClass& second) (or with whatever return value you want this to have).

Note also that I needed the friendship declaration only for my non-member operator to have an access to the private _a field.

Upvotes: 0

ScarletAmaranth
ScarletAmaranth

Reputation: 5101

If you overload an operator as a non-member function, you need to specify an object which you want to operate on specifically in your argument list.

If you overload it as a member function, the "this" pointer will do part of the work for you.

Consider the following example:

class Test {
   public:
   friend Test operator+(const Test &lhs, const Test &rhs); // Non-member function
   Test operator+(const Test &rhs); // Member function
};

The difference between the two is that the non-member function doesn't have the this pointer that compiler conveniently passes for you whenever you're talking about a specific instance of a class.

The member function one has the lhs inferred, therefore you need to provide only the rhs.

Please do note that the "friend" is not necessary but if you want to access Test's private members, you need it.

Compiler can disambiguate based on the parameter count. If you wanted to declare friend Test operator+(const Test &rhs), it would complain about insufficiency of arguments because + is a binary operator. The lhs of a member function operator+ is "this".

Upvotes: 1

Jim Hansson
Jim Hansson

Reputation: 142

example

class Foo {
public:
  Foo operator+(Foo) // member variant
  // declared inside the function
}; // end of class

Foo operator+(Foo lhs, Foo rhs) // non-member variant
{ // declared outside the class
  // could be just a call to the member variant
  lhs.operator+(rhs);
  // I usually do this when implementing std::stream operators,
  // don't remember why just now.
}

the non-member does not need to be friended but may be if it need access to internal state. the non-member has some advantages when it comes to templated code and namespaces on some compilers if I remember correctly, It can also be fine to friend in the non-member variant to document that there is a function outside the class that is somewhat specific to this class. It tells me that if I change that class I may have to look over the non-member operator to make sure that I have not broken anything.

Upvotes: 0

Related Questions