Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Whether to go for a member function or friend function when the function is supposed to change state of object?

In the book The C++ Programming Language, by Bjarne Stroustrup, the author introduces a class Matrix which has to implement a function inv(). In section 11.5.1, he talks about two possibilities of doing that. One is to make a member function and other is to make a friend function inv(). Then towards the end of section 11.5.2, where he talks about making the choice of whether to use a friend or a member function, he says:

If inv() really does invert Matrix m itself, rather than returning a new Matrix that is the inverse of m, it should be a member.

Why is it so? Can't a friend function change the state of the Matrix and return the reference to that matrix? Is it because of the possibility of passing a temporary matrix when we call the function?..

like image 827
sajas Avatar asked Oct 10 '12 05:10

sajas


People also ask

Should my class declare a member function or a friend function?

The friend function can be a member of another class or a function that is outside the scope of the class. A friend function can be declared in the private or public part of a class without changing its meaning. Friend functions are not called using objects of the class because they are not within the class's scope.

When should a function be a member function?

One way to look at this is this: If a function manipulates an object's inner state, then that's a good indication that this function should probably be a member function. If a function uses an object without changing its inner state, then that's a good indication that this function probably should be a free function.

What are the advantages of friend function over member function?

Benefits of friend function A friend function is used to access the non-public members of a class. It allows to generate more efficient code. It provides additional functionality which is not normally used by the class. It allows to share private class information by a non member function.


1 Answers

To be honest, I think the only reasons to make such a decision are syntactic convenience and tradition. I'll explain why by showing what are (not) the differences between the two and how these differences matter when making a decision.

What differences are there between non-member friend functions and public member functions? Not much. After all, a member function is just a regular function with a hidden this parameter and access to the class's private members.

// what is the difference between the two inv functions?
// --- our code ---
struct matrix1x1 { // this one is simple :P
private:
    double x;
public:
    //... blah blah
    void inv() { x = 1/x; }
    friend void inv(matrix1x1& self) { self.x = 1/self.x; }
};
matrix1x1 a;

// --- client code ---

// pretty much just this:
a.inv();
// vs this:
inv(a);

void lets_try_to_break_encapsulation(matrix1x1& thingy) {
    thingy.x = 42; // oops, error. Nope, still encapsulated.
}

They both provide the same functionality, and in no way do they change what other functions can do. The same internals get exposed to the outside world: there's no difference in terms of encapsulation. There's absolutely nothing that other functions can do differently because there's a friend function that modifies private state.

In fact, one could write most classes with most functions as non-member friend functions (virtual functions and some overloaded operators must be members) providing the exact same amount of encapsulation: users cannot write any other friend function without modifying the class, and no function other than the friend functions can access private members. Why don't we do that? Because it would be against the style of 99.99% of C++ programmers and there's no great advantage to be taken from it.

The differences lie in the nature of the functions and the way you call them. Being a member function means you can get a pointer to member function from it, and being a non-member function means you can get a function pointer to it. But that's rarely relevant (especially with generic function wrappers like std::function around).

The remaining difference is syntactic. The designers of the D language decided to just unify the whole thing and say that you can call a member function directly by passing it an object like inv(a), and call a free function as a member of its first argument, like a.inv(). And no class suddenly got badly encapsulated because of that or anything.1

To address the particular example in the question, should inv be a member or a non-member? I'd probably make it a member, for the familarity argument I outlined above. Non-stylistically, it doesn't make a difference.


1. This is unlikely to happen in C++ because at this point it would be a breaking change, for no substantial benefit. It would, for an extreme example, break the matrix1x1 class I wrote above because it makes both calls ambiguous.

like image 143
R. Martinho Fernandes Avatar answered Oct 12 '22 23:10

R. Martinho Fernandes