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

StackOverflow https://stackoverflow.com/questions/381164

  •  22-08-2019
  •  | 
  •  

Вопрос

В шапке вижу, что не сам себе писал следующее:

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

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

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

Это было полезно?

Решение

friend inline bool operator==(MonitorObjectString& lhs, MonitorObjectString& rhs) { 
    return(lhs.fVal==rhs.fVal); 
}

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

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

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

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

Другие советы

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

Грамматически говоря...

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


Однако это можно было бы реализовать более чисто следующим образом:

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top