Effective C++ item 23: Prefer Non-member Non-friend Functions to Member Functions

Imagine you have following class

1
2
3
4
5
6
7
8
class WebBrowser {
public:
...
void clearCache();
void clearHistory();
void removeCookies();
...
};

We want to add another function clearEverything which calls clearCache, clearHistory and removeCookies. Which way is better?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// first approach is add clearEverything as member function
class WebBrowser {
public:
...
void clearEverything() {
clearCache();
clearHistory();
removeCookies();
}
...
};

// second approach is add non-member function
void clearBrowser(WebBrowser& wb)
{
wb.clearCache();
wb.clearHistory();
wb.removeCookies();
}

Second approach is better, because it provides better encapsulation. The more public methods which can access private data, the worse encapsulation the class has. In the second approach, it uses existing method of WebBrowser without add public interface to it, which yields better encapsulation.

Above example, clearBrowser is a utility funtion which client can call. Defining it in a namespace related to WebBrowser class is a nature way of providing the functionality. If you have other utility function which may not be needed by all clients, you can even distribute them into different header files with same namespace to provide better isolation of functionalities. This is how STL organize it’s classes and functioinalities. Rather than having a single monolithic <C++StandardLibrary> header containing everything in the std namespace, there are dozens of headers (e.g., <vector>, <algorithm>, <memory>, etc.), each declaring some of the functionality in std.

Practically speaking, you can implement WebBrowser related functionality as following

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// header "webbrowser.h" — header for class WebBrowser itself
// as well as "core" WebBrowser-related functionality
namespace WebBrowserStuff {
class WebBrowser { ... };
void clearBrowser(WebBrowser& wb) { ... };
}
// header "webbrowserbookmarks.h"
namespace WebBrowserStuff {
void addBookmark(WebBrowser& wb) { ... };
}
// header "webbrowsercookies.h"
namespace WebBrowserStuff {
void validateCookies(const WebBrowser& wb) { ... };
}

Reference:
“Effective C++” Third Edition by Scott Meyers.