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 then?
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
from algorithm
. For instance vector
class does not have a sort
function and one uses the stl sort
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 as assign
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?
Access to the book is by no mean necessary.
The issues we are dealing here are Dependency and Reuse.
In a well-designed software, you try to isolate items from one another so as to reduce Dependencies, because Dependencies are a hurdle to overcome when change is necessary.
In a well-designed software, you apply the DRY principle (Don't Repeat Yourself) because when a change is necessary, it's painful and error-prone to have to repeat it in a dozen different places.
The "classic" OO mindset is increasingly bad at handling dependencies. By having lots and lots of methods depending directly on the internals of the class, the slightest change implies a whole rewrite. It need not be so.
In C++, the STL (not the whole standard library), has been designed with the explicit goals of:
Therefore, the Containers expose well-defined interfaces that hide their internal representations but still offer sufficient access to the information they encapsulate so that Algorithms may be executed on them. All modifications are made through the container interface so that the invariants are guaranteed.
For example, if you think about the requirements of the sort
algorithm. For the implementation used (in general) by the STL, it requires (from the container):
Thus, any container that provides Random Access and is not Associative is (in theory) suitable to be sorted efficiently by (say) a Quick Sort algorithm.
What are the Containers in C++ that satisfy this ?
deque
vector
And any container that you may write if you pay attention to these details.
It would be wasteful, wouldn't it, to rewrite (copy/paste/tweak) sort
for each of those ?
Note, for example, that there is a std::list::sort
method. Why ? Because std::list
does not offer random access (informally myList[4]
does not work), thus the sort
from algorithm is not suitable.