Friends are iffy in that they greatly increase the coupling in your program, which is something that you generally want to reduce. Indeed, friendship is the tightest coupling there is, followed by inheritance (because friendship grants access to all members, whereas inheritance still denies access to private members).
The thing to keep in mind is the distinction between interface and implementation. A well-designed class will present a good, useful interface to the rest of the world. The implementation of that interface, however, should be hidden. The rest of the program should not be interested in
how the class works, only in what it does. By hiding the implementation, you give yourself the freedom to change that implementation at will without affecting the rest of the program. Expose any part of your implementation and you have to be very careful about changing it, because other classes and functions may be dependent on the specifics (IOW, you have high coupling between classes).
Implementation hiding reaches its peak with the pimpl idiom, where the class consists
only of public function members and a single pointer to an implementation class:
Code:
class foo
{
public:
// function members
private:
class fooimpl* pimpl;
};
Using this idiom, the entire implementation is hidden away in the implementation file. The outside world only sees a single name (fooimpl), without even a class definition - and even the little bit that can be "seen" is private. The freedom this gives you to radically alter the implementation is unrivalled - you cannot affect anyone else, even if you completely rewrite the implementation. And, since changing the implementation doesn't even affect the header file, a complete rewrite of the implementation
still only requires the recompilation of a single file. (Of course, if the new implementation is rubbish, that is a sort of effect, but that's not what I mean.)
The protected section of a class is there to provide an
interface for use by derived classes only - it's like the public section apart from restricted access.
This is not about style, this is about clean code, maintainable code,
robust code - code that you can muck about with without having the whole edifice collapse around your ears; code that you're not afraid to make improvements to, because you know changes will be localised and easily undone.
My personal approach to the implementation of a class's (public and protected) interface is:
1) Whenever possible, make it invisible (using pimpl).
2) If I can't make it invisible, make it private.
3) If I can't make it private, retire, because I've forgotten how to write C++.
Your mileage may vary, of course. I've described a personal approach, one which comes from viewing C++ classes not as blobs that contain functions and data, but as entities that provide an interface and an implementation of that interface. To my mind, data members are implementation, with very few exceptions (I can't think of one at the moment), so should be hidden from everyone.