Meyers mentioned in his book Effective C++ that in certain scenarios non-member non-friend functions are better encapsulated than member functions.
Example:
// Web browser allows to clear something
class WebBrowser {
public:
...
void clearCache();
void clearHistory();
void removeCookies();
...
};
Many users will want to perform all these actions together, so WebBrowser
might also offer a function to do just that:
class WebBrowser {
public:
...
void clearEverything(); // calls clearCache, clearHistory, removeCookies
...
};
The other way is to define a non-member non-friend function.
void clearBrowser(WebBrowser& wb)
{
wb.clearCache();
wb.clearHistory();
wb.removeCookies();
}
The non-member function is better because "it doesn't increase the number of functions that can access the private parts of the class.", thus leading to better encapsulation.
Functions like clearBrowser
are convenience functions because they can't offer any functionality a WebBrowser
client couldn't already get in some other way. For example, if clearBrowser
didn't exist, clients could just call clearCache
, clearHistory
, and removeCookies
themselves.
To me, the example of convenience functions is reasonable. But is there any example other than convenience function when non-member version excels?
More generally, what are the rules of when to use which?
begin()
/end()
functions that were added to the new standard (which allow you to iterate static arrays as well as containers). – Wessonstd::string
and the mentioned rules collide. – Mahoundstd::string
class. Also, there are too many things in the Standard library which aren't reasonable, but they are there for a reason, and the reason is called compatibility. – Shultsstring
class existed (more or less) prior to the Standard design, you will notice it is totally at odd with the rather modern design of the STL part of the Standard Library. One key flaw is the redundancy between index-based and iterator-based methods as well as the customfind
set that collide with<algorithm>
find flavors. You may also note that IOStreams is itself apart from the others, once again it's historical and was kept for compatibility reasons. See Sutter's take on the interface at gotw.ca/gotw/084.htm – Zerlinastd::string
existed much before Scott Meyer came up with these rules and lots of other recent idioms and techniques discovered by other experts. Having said that, now if the non-member and non-friend is a reasonable choice, the implementation ofstd::string
would remain same, just to be compatible with the old code. That is what I think. – Shults