friend inline bool operator==(MonitorObjectString& lhs, MonitorObjectString& rhs) {
return(lhs.fVal==rhs.fVal);
}
называется friend definition
. Она определит функцию как функцию, не являющуюся членом пространства имен, окружающего класс, в котором она появляется. На самом деле, встроенная строка избыточна: она неявно объявляется встроенной, если это определение друга. Некоторые плюсы и минусы этого:
- Это делает оператора невидимым для обычного поиска. Единственный способ, которым вы можете вызвать это, - использовать поиск по аргументам. Это сделает пространство имен свободным от множества объявлений операторов, видимых как обычно. Обратите внимание, что это также отключит возможность его вызова с использованием неявных преобразований в MonitorObjectString (потому что, если оба типа аргументов не совпадают во время поиска кандидатов для вызова, зависимый от аргумента поиск не найдет функцию).
- Поиск имен начинается в области действия класса, в котором отображается определение друга. Это означает, что не нужно записывать длинные имена типов или другие имена. Просто отошлите их, как в обычной функции-члене класса.
- Будучи другом, функция видит внутренние элементы
MonitorObjectString
. Но это ни хорошо, ни плохо. Это зависит от ситуации. Например, если есть функции getFVal()
, дружить с этой функцией довольно бессмысленно. Тогда можно использовать getFVal
.
Раньше мне нравился стиль операторов определения друга, потому что они имеют прямой доступ к членам класса и появляются в определении класса - так что я мог иметь «все с одного взгляда». Однако недавно я пришел к выводу, что это не всегда хорошая идея. Если вы можете (и должны) реализовывать оператор, просто используя открытые функции-члены класса, вы должны сделать его оператором, не являющимся другом (и не членом), определенным в том же пространстве имен класса. Он гарантирует, что если вы измените какую-то реализацию - но оставите интерфейс класса прежним - оператор все равно будет работать, и у вас будет меньше каскадных изменений, потому что вы знаете, что он не может получить доступ к деталям реализации.
Однако , я предпочитаю этот стиль, чем написание операторов-членов, потому что операторные функции в области именного пространства обладают дополнительными функциями симметричности с их аргументами: они не обрабатывают левую сторону особой, потому что обе стороны это просто обычные аргументы, а не объектные аргументы, связанные с *this
. Если левая или правая сторона относятся к типу вашего класса, другая сторона может быть неявно преобразована - независимо от того, является ли она левой или правой. Для функций, которые также определены без синтаксиса определения друга (традиционно в области пространства имен), у вас будет возможность выборочно включать заголовки, которые делают эти операторы доступными или нет.