Функции-члены и функции-нечлены?

каково ваше правило, для каких функций, которые работают с классом, должны быть функциями-членами и функциями, не являющимися членами? Например, у меня есть класс, который представляет лабиринт, используя матрицу булов. Я делаю функцию под названием isConnected, которая проверяет, что 2 точки в лабиринте находятся в одной области (т. е. можно путешествовать от A до B).

должен ли это быть член или не член? Что такое хорошее правило?

6 ответов


когда сделать его функцией-членом:

  • когда функция логически связана с классом (например, ваш пример связности лабиринта)
  • когда функция должна получить доступ к закрытым или защищенным членам, лучше сделать его членом, чем друг.

когда сделать его автономной функцией

  • когда это общая функция, которая может быть шаблонизирована для естественной работы с другими классами (посмотрите на заголовок для хорошего примера)

Херб Саттер говорит:" Мы хотим, чтобы они не были друзьями, если это возможно", и он умнее меня.

http://www.gotw.ca/gotw/084.htm


Ну, есть аргументы для обоих.

в пользу функций, не являющихся членами:

  • предлагает лучше инкапсуляции
  • это позволяет лучше повторно использовать код (std:: find можно повторно использовать для любой тип контейнера, потому что это бесплатная функция. Если бы это был член, любой контейнер должен был бы определить свой собственный)
  • это делает много общих трюков программирования проще. (container.begin() недопустимо, если container это матрица. Это делает немного более неудобным писать общий код, работающий с контейнерами. Но!--2--> можно сделать допустимым для любого типа, даже встроенных, таких как массивы). Он также может сделать миксины через композицию намного чище, потому что он не требует, чтобы пользователь "расставлял точки" через членов, чтобы добраться до объекта mixin, с которым вы хотите работать.

в пользу создания функций-членов вещей:

  • это знакомо. Java и C# требуются это, и в глазах многих программистов, функции-члены синонимичны ООП.

и... вот и все. (Но этот аргумент не следует недооценивать. Читаемость кода важна, и если людям легче читать версию члена, это сильный аргумент в его пользу. Это просто не дает лучшего кода. С точки зрения строгого" лучшего кода", по возможности, следует отдавать предпочтение нечленам.


в этом случае, я бы пошел на функцию-член. Правило, которому я следую, заключается в том, что если функция должна получить доступ к чему-то, что является внутренним текущего состояния экземпляра, то она должна быть частью "области" класса. В этом случае связность A и B зависит от состояния экземпляра объекта.

конечно, вы можете в конечном итоге иметь класс, имеющий слишком много обязанностей. В этом случае включается простой фактор keep it, и вы должны учитывать, если ваш класс пытается сделать слишком много. Тогда было бы удобно иметь отдельный класс (например, в вашем случае ConnectednessEvaluator), чья конкретная роль заключается в том, чтобы содержать алгоритмы, которые могут пересекать и действовать на ваших экземплярах лабиринта.


Я всегда ссылаюсь на FAQ 13.9. Это не точная наука, а наука, основанная на осмотрительности.

Это было бы упрощением сказать, что всякий раз, когда вам нужен доступ к внутренностям класса, вы должны использовать член. Примечательными примерами являются операторы вставки/извлечения потока (>> и << соответственно) и бинарных +.

в вашем примере isConnected - Это метод проверки состояния объекта, т. е. инспектор и идеальный кандидат за членство.


единственное, что я, как правило, делаю функциями, не являющимися членами,-это вещи, которые вызываются только изнутри функций-членов (не должны быть видны вне класса), и могут отлично работать с открытыми членами класса и/или небольшим количеством параметров.