Делайте функцию членом только если ей нужен прямой доступ к представлению класса
Причина
Меньше связанности, чем при использовании функций-членов, меньше функций, которые могут вызвать проблемы, изменяя состояние объекта, меньше функций, которые нужно изменять после изменения представления.
Пример
class Date {
// ... относительно небольшой интерфейс ...
};
// вспомогательные функции:
Date next_weekday(Date);
bool operator==(Date, Date);
«Вспомогательным функциям» не нужен прямой доступ к представлению Date.
Примечание
Это правило стало бы ещё лучше, если бы C++ получил «единый синтаксис вызова функций».
Исключение
Язык требует, чтобы virtual функции были членами, и не все virtual функции напрямую обращаются к данным. В частности, члены абстрактного класса редко это делают.
Заметьте о мультиметодах.
Исключение
Язык требует, чтобы операторы =, (), [] и -> были членами.
Исключение
Набор перегрузок может содержать члены, которые не обращаются напрямую к private данным:
class Foobar {
public:
void foo(long x) { /* манипуляция private данными */ }
void foo(double x) { foo(std::lround(x)); }
// ...
private:
// ...
};
Исключение
Аналогично, набор функций может быть спроектирован для использования в цепочке:
x.scale(0.5).rotate(45).set_color(Color::red);
Обычно некоторые, но не все такие функции напрямую обращаются к private данным.
Контроль
Сложность в том, что многие функции-члены, которым не нужно напрямую обращаться к данным, всё же это делают.
- Искать не-
virtualфункции-члены, которые не обращаются напрямую к членам данных. - Игнорировать
virtualфункции. - Игнорировать функции, входящие в набор перегрузок, из которых хотя бы одна обращается к
privateчленам. - Игнорировать функции, возвращающие
this.