друг И встроенный метод, какой смысл?

Я вижу в заголовке, что я сам не написал следующее:

class MonitorObjectString: public MonitorObject {
   // some other declarations
   friend inline bool operator==(MonitorObjectString& lhs, MonitorObjectString& rhs) { return(lhs.fVal==rhs.fVal); }

Я не могу понять, почему этот метод объявлен как друг. Я подумал, что будет иметь смысл, если функция определена в другом месте и ей нужен доступ к внутреннему члену класса, но здесь это не так, поскольку она встроенная и даже не требует доступа к членам.

Как вы думаете? «Друг» бесполезен?

Ответы на вопрос(3)

friend ключевое слово все еще необходимо, чтобы сообщить компилятору, что эта функция не является членом класса,РЕДАКТИРОВАТЬ: но вместо этого функция, не являющаяся членом, которая может видеть закрытые члены класса.

Тем не менее, это можно было бы реализовать более четко, как это:

/* friend */ inline bool operator ==(const MonitorObjectString& rhs) const
{ return fVal == rhs.fVal; }

(Конечно, я предполагаюfVal имеет подходящий тип, который можно сравнивать, не влияя на его постоянство.)

 pyon21 дек. 2008 г., 00:53
Я никогда не применяю operator == в классах с какой-то злой иерархией.
 pyon19 дек. 2008 г., 16:18
Коппро, вы можете сделать это (на самом деле, я делаю это довольно часто): // внутри оператора bool определения CSomeClass == (const CSomeClass & rhs) const / * обратите внимание на это * /;
 Barth19 дек. 2008 г., 16:11
это строка, так что все должно быть в порядке, не так ли?
 Johannes Schaub - litb07 февр. 2009 г., 07:39
Эдуардо, как это "чище"? он имеет такой же доступ к частному члену и стал участником. так что у него сильная связь, которая хуже. определение друга будет чище, имхо.
 pyon19 дек. 2008 г., 16:04
Нет, потому что это функция-член того же класса.
 Barth19 дек. 2008 г., 16:02
а тут друг не нужен?
 Greg Rogers19 дек. 2008 г., 16:21
хорошая точка Коппро.
 Iraimbilanja16 апр. 2009 г., 23:12
Коппро, замечательно, никогда не осознавал этого.
 pyon19 дек. 2008 г., 16:16
<I> должно быть </ i> нормально, если используемые вами строковые классы хорошо спроектированы.
 pyon21 дек. 2008 г., 01:13
Я кое-что забыл: оператор перегрузки == не имеет смысла, когда сравниваемый объект не имеет семантики значений. Наследование не имеет смысла, когда они делают.
 Drew Dormann19 дек. 2008 г., 17:44
Ваше «более чистое» решение многими считается плохим дизайном. Если я создаю «ShmooptyString», который может неявно преобразовывать в «MonitorObjectString», код MOS == SS будет компилироваться, а SS == MOS - нет. Проблема в том, что параметры допускают неявные преобразования, но вы не можете неявно преобразовать «это»
 pyon19 дек. 2008 г., 16:09
Если тип fVal определен языком (например, int, double и т. Д.), Проблем не должно быть.
 coppro19 дек. 2008 г., 16:16
Результат похож; но в общем случае немодифицирующие операторы должны предпочитать быть нечленами, потому что, если оператор является функцией-членом, компилятор не может преобразовать левый тип в тип класса; в то время как это может быть с функцией, не являющейся членом.
 Barth19 дек. 2008 г., 16:08
Ваше предложение похоже (в действительности) на оригинальное? Или мне следует ожидать каких-то проблем, если я использую ваше предложение вместо оригинального? Большое спасибо за вашу помощь
 Johannes Schaub - litb07 февр. 2009 г., 07:41
также обратите внимание на то, что сказал Коппро: если вы поставите его как не являющийся членом, компилятор может преобразовать один из его операндов, если другой имеет правильный тип (если вы используете определение друга) - но не если вы используете определение члена оператора ==.

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

 Barth19 дек. 2008 г., 16:03
Хорошо, я понимаю лучше. Но так как этот метод является членом класса, зачем вам объявлять его другом?
 Johannes Schaub - litb07 февр. 2009 г., 07:43
но тем не менее, «встроенный»имеет последствия. это не так, как это бесполезно. это создаст особые полезные предпосылки в отношении УСО. во всяком случае, встроенныйявляется избыточно здесь, потому что функция, определенная в определении друга, неявно встроена
 eduffy19 дек. 2008 г., 16:49
@ Барт - Эдуардо прав. Если вы поставите друга перед функцией, она будет автономной! не метод. Вот почему это требует ДВА! Параметры, не подразумеваемые "это".
 pyon19 дек. 2008 г., 16:04
Если это друг, это не член класса.
 Martin York19 дек. 2008 г., 18:03
Ключевое слово «inline» не означает, что оно на самом деле встроено в код. Это «подсказка» компилятору. Компилятор будет ТОЛЬКО встроенным, если в этом есть смысл.
Решение Вопроса
friend inline bool operator==(MonitorObjectString& lhs, MonitorObjectString& rhs) { 
    return(lhs.fVal==rhs.fVal); 
}

friend definition, Она определит функцию как функцию, не являющуюся членом пространства имен, окружающего класс, в котором она появляется. На самом деле, встроенная строка избыточна: она неявно объявляется встроенной, если это определение друга. Некоторые плюсы и минусы этого:

Это делает оператора невидимым для обычного поиска. Единственный способ, которым вы можете вызвать это, - использовать поиск по аргументам. Это сделает пространство имен свободным от множества объявлений операторов, видимых как обычно. Обратите внимание, что это также отключит возможность его вызова с использованием неявных преобразований в MonitorObjectString (потому что, если оба типа аргументов не совпадают во время поиска кандидатов для вызова, зависимый от аргумента поиск не найдет функцию).Поиск имен начинается в области действия класса, в котором находится определение друга. Это означает, что не нужно выписывать длинные имена типов или другие имена. Просто отошлите их, как в обычной функции-члене класса.Как это друг, функция видит внутренностиMonitorObjectString, Но это ни хорошо, ни плохо. Это зависит от ситуации. Например, если есть функцииgetFVal() делать функцию друга довольно бессмысленно. Мог бы использоватьgetFVal как хорошо тогда.

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

тем не мениеЯ предпочитаю этот стиль, чем написание операторов-членов, потому что операторные функции в области имен имеют дополнительные возможности симметричности с их аргументами: они не обрабатывают левую сторону как особую, поскольку обе стороны являются просто обычными аргументами, а не объектными аргументами связан с*this, Если левая или правая сторона относятся к типу вашего класса, другая сторона может быть неявно преобразована - независимо от того, является ли она левой или правой. Для функций, которые также определены без синтаксиса определения друга (традиционно в области пространства имен), у вас будет возможность выборочно включать заголовки, которые делают эти операторы доступными или нет.

Ваш ответ на вопрос