friend vs member functions in Operator Overloading C++
Asked Answered
E

4

19

Previously I learnt about overloading Operators in C++ as member functions as well as friend functions of a class. Although, I know how to overload operators in C++ using both techniques. But I am still confused that ** which one is better** ? A member function or a friend function to overload operators, which one should i use and why? Please guide me ! Your response will be appreciated greatly. I shall be glad and thankful for your answers.

Eggshaped answered 29/3, 2017 at 9:15 Comment(4)
What about global non-friend functions? Well, either way, always prefer to go global than member.Cutlass
global non-friend functions? I thought an overloaded operator can be only friend or member function. But thanks ! I will search on that too.Eggshaped
friend is only needed to give the function access to the class's private and protected members. Otherwise if that is not needed then friend is not needed either.Cutlass
Yes Sir @DeiDei I know that well about friend functions. Just wanted to ask that which one is better ! :-) Thanks for your response Sir :-)Eggshaped
A
12

The choice isn't "member or friend" but "member or non-member".
(Friendship is frequently overused, and usually taught much too early in schools.)

This is because you can always add a public member function that a free function can call.

For instance:

class A
{
public:
    explicit A(int y) : x(y) {}
    A plus(const A& y) const { return A{x + y.x}; }
private:
    int x;
};

A operator+(const A& lhs, const A& rhs) { return lhs.plus(rhs); }

As for how to choose: if the operator doesn't take an instance of the class as its left-hand operand, it must be a free function, otherwise it's pretty much a matter of personal taste (or coding standards if you're not alone).

Example:

// Can't be a member because the int is on the left.
A operator+ (int x, const A& a) { return A{x} + a; }

For operators that have a corresponding mutating operator (like + and +=), it's common to do the mutating operator as a member and the other as a non-member:

class B
{
public:
    explicit B(int y) : x(y) {}
    B& operator+= (const B& y) { x += y.x; return *this; }
private:
    int x;
};

B operator+(B lhs, const B& rhs) { return lhs += rhs; }

but you can spell this out too, of course:

class C
{
public:
    explicit C(int y) : x(y) {}
    C& add(const C& y) { x += y.x; return *this; }
private:
    int x;
};

C& operator+=(C& lhs, const C& rhs) { return lhs.add(rhs); }
C operator+(C lhs, const C& rhs) { return lhs += rhs; }
Araliaceous answered 29/3, 2017 at 9:56 Comment(0)
S
3

There is probably not a fixed rule for this so I just give my opinion: when possible use member function for operator overloading. The main reason for this is that I see operators as integral part of the class and the logic of the class is more localized.

The reason for prefering free functions for operator overloading would be to keep the class as lean as possible (only use friend when needed).

In some cases operators can't be members, so there is no discussion in that case. Mainly member functions have the class instance as first parameter which isn't always possible (e.g. operator<< for i/o).

Shon answered 29/3, 2017 at 9:34 Comment(0)
B
3

Member functions and friend are not two opposite among which you need to choose only one. They both can be used, for example to avoid duplicating code by implementing one and making the other calling it.

struct A
{
    A operator+=(A const & second); 
};

A operator+(A const &first, A const &second)
{
    A temp(first);
    temp += second;
    return temp;
}

But in case if you want to choose for one function if it needs to be member or not, here is a rule that I follow : to implement a non-member function (friend or not) when I have a binary operator to respect the symmetry we expect. Example : with A and the possibility to convert a int to A implicitly (with a constructor taking a int), if I have a member function, there what will be the result.

A a1, a2; 
a1 + a2; // OK 
a1 + 42; // OK
42 + a2; // KO

With a free function, there is the result.

A a1, a2; 
a1 + a2; // Ok 
a1 + 42; // Ok 
42 + a2; // Ok

An concrete C++ class that use this possibility is std::string.

#include <iostream>
#include <string>

int main()
{
    std::string s {"World"};
    // Works with absolutely no problem.
    std::string chaine = "Hello " + s;
    std::cout << chaine << std::endl;
}

To conclude, here is a good link on SO to help you.

Braasch answered 29/3, 2017 at 9:49 Comment(0)
C
3

Not far from a matter of taste, but some use cases clearly require one of the two ways.

When the operator takes as arguments only members of the class you are designing, encapsulation votes for using a member function. Example: addition of two objects:

class A {
    ...
    A operator + (const class A& other);   // naturally a member function
    ...
};

In the opposite, when the member of the class you are writing is the second argument of the operator, you can only use a friend function

std::outstream& operator << (std::outstream& out, const class A& a);

class A {
    ...
    friend std::outstream& operator << (std::outstream& out, const class A& a); // must be friend here
};

At most it could be a member of std::outstream but A class did not exist when std::outstream class was created in the standard C++ library...

Chemisorb answered 29/3, 2017 at 9:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.