TITLE: Beating friends into the ground PROBLEM: Eric Meijer IOStreams without friends are *EASY*: class foo { (...) public: void print(ostream &); // can be inlined, void read(istream &); // if you like } inline ostream &operator<<(ostream &os, foo &f) { f.print(os); return os; } inline istream &operator(istream &is, foo &f) { f.read(is); return is; } RESPONSE: pete@genghis.interbase.borland.com (Pete Becker), Borland Yes, and that proves the point. This is not clean, because it provides two publicly accessible functions that do the same thing. By trying to avoid friends this code makes available for use what should be an internal implementation detail, namely, the functions print() and read(). Now, if there are good reasons to expose these to users, that's fine. But exposing them only to avoid friends is not a good reason. RESPONSE: clamage@taumet.Eng.Sun.COM (Steve Clamage), 17 May 94 Exactly so. One sometimes hears that friend functions "violate encapsulation". While it is certainly possible to violate encapsulation using friend functions, I prefer to view friend functions simply as part of the public interface of the class. That is the point Pete is making. If a function is logically part of the public interface of a class (such as I/O, or addition for complex numbers), but cannot be a member because you don't want the class object as the first parameter, or because you want type conversions enabled on the first parameter), then make it a friend function. Please note that every function which has access to the private members of a class is listed explicitly in the class declaration, either as a member function or as a friend function. You therefore always have a complete list of all functions which could be affected by changes to the private section.