Why do common programming constructs prefer free functions over member functions?

I recently introduced the design of common programming libraries such as STL, boost :: graph, boost PropertyMaps http://www.boost.org/doc/libs/1_54_0/libs/property_map/doc/property_map.html

What is the point of using free features like get (PropertyMap, key) over member functions like PropertyMap.get (key)?

I understand that the most common form of these functions is defined in the namespace "boost". Suppose I define a new PropertyMap in my namespace "space", what is the best place to define its corresponding get function? "boost" or "project"

+4
source share
4 answers

The main motivation is that by preferring non-member nonfriend functions, you can simplify classes as much as possible. See Herb Sutter's Article here: http://www.gotw.ca/publications/mill02.htm .

This article also provides an answer to another part of your question, where to put the appropriate get function. This is a C ++ function called argument dependent (ADL). From Herb Sutter, who calls it Koenig's search, although this name is controversial (see Comments below):

A Koenig search says that if you provide an argument to a class function, enter, then, to find the name of the function, the compiler must look not only in ordinary places, such as the local area, but also in the namespace (here NS), which contains the type of the argument.

Here is an example:

namespace MyNamespace { class MyClass {... }; void func(MyClass); } int main(int aArgc, char* aArgv[]) { MyNamespace::MyClass inst; func(inst); // Ok, because Koenig says look in the argument namespace for func } 

So you just declare a get function in the same namespace as your class.

Remember that this does not work for template functions if you must explicitly specify template parameters - see this post: fooobar.com/questions/82370 / ...

+3
source

There are two different reasons:

  • Better encapsulation : By minimizing the number of functions that have access to class attributes, you improve encapsulation.

  • Extensibility : in C ++, the namespace definition is open (you can add to it), while the class definition is closed; therefore, you can add free functions but not perform member functions.

While encapsulation is more a matter of taste, extensibility is extremely important for general programming. You do not want to abandon a third-party type just because it does not need one method that you need ... and, of course, some types (for example, built-in types or standard library types) cannot be extended at all.

+6
source

Free functions are less closely related to a specific implementation (since they rely only on the open interface of the container). This provides greater flexibility and ease of maintenance.

You will notice that when a particular implementation is important (for example, std::map::find ), the standard library uses member functions.

Scott Meyers has a set of rules that work very well for deciding how to create your functions: http://cpptips.com/nmemfunc_encap

+4
source

The key to the question, I think, makes it more general. A free function of type std::find() can be used with a large number of different containers and therefore is common - a member of the type std::map<T>.find() works only with std::map and, therefore, is not general at all.

With good universal functions, you should be able to create your own containers that can interact with them, eliminating the need to write your own methods in your container (as well as the need to write your own free functions, obviously). It makes sense to provide a method when you have a container for which a particular operation can be implemented better defined for that container than in a general function (example std::map find() , which is an obvious example).

+2
source

Source: https://habr.com/ru/post/1491929/


All Articles