While puzzling with some facts on class design, specifically whether the functions should be members or not, I looked into Effective c++ and found Item 23, namely, Prefer non-member non-friend functions to member functions. Reading that at first hand with the web browser example made some sense, however convenience functions( named the nonmember functions like this in the book) in that example change the state of the class, don't they?
So, first question, should not they be members than?
Reading a bit further, he considers the STL functions and indeed some functions which are not implemented by some classes are implemented in stl. Following the ideas of the book they evolve into some convenience functions that are packed into some reasonable namespaces such as
std::sort
,std::copy
fromalgorithm
. For instancevector
class does not have asort
function and one uses the stlsort
function so that is not a member of the vector class. But one could also stretch the same reasoning to some other functions in vector class such asassign
so that could also not be implemented as a member but as a convenience function. However that also changes the internal state of the object like sort on which it operated. So what is the rationale behind this subtle but important (I guess) issue.
If you have access to the book can you clarify these points a bit more for me?
The motivation is simple: maintain a consistent syntax. As the class evolves or is used, various non-member convenience functions will appear; you don't want to modify the class interface to add something like
toUpper
to a string class, for example. (In the case ofstd::string
, of course, you can't.) Scott's worry is that when this happens, you end up with inconsistent syntax:By only using free functions, declaring them friend as needed, all functions have the same syntax. The alternative would be to modify the class definition each time you add a convenience function.
I'm not entirely convinced. If a class is well designed, it has a basic functionality, it's clear to the user which functions are part of that basic functionality, and which are additional convenience functions (if any such exist). Globally, string is sort of a special case, because it is designed to be used to solve many different problems; I can't imagine this being the case for many classes.