Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

friend vs member functions in Operator Overloading C++

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.

like image 681
HN Learner Avatar asked Mar 29 '17 09:03

HN Learner


2 Answers

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; }
like image 190
molbdnilo Avatar answered Oct 18 '22 21:10

molbdnilo


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.

like image 29
informaticienzero Avatar answered Oct 18 '22 23:10

informaticienzero