Какие операторы C ++ не могут быть перегружены без функции друга? - PullRequest
2 голосов
/ 24 октября 2011

Какие операторы C ++ вообще не могут быть перегружены без функции друга?

Ответы [ 7 ]

4 голосов
/ 24 октября 2011

Объявление о дружбе требуется только в том случае, если:

  1. Вы определяете оператор как отдельную функцию вне класса, а
  2. Реализация должна использовать закрытые функции или переменные.

В противном случае вы можете реализовать любой оператор без объявления друга. Чтобы сделать это немного более конкретным ... можно определить различные операторы как внутри, так и вне класса *:

 // Implementing operator+ inside a class:
 class T {
   public:
    // ...
    T operator+(const T& other) const { return add(other); }
    // ...
 };

 // Implementing operator+ outside a class:
 class T {
   // ...
 };

 T operator+(const T& a, const T& b) { return a.add(b); }

Если в приведенном выше примере функция add была закрытой, то в последнем примере должна быть декларация друга, чтобы operator+ могла ее использовать. Однако, если «add» является публичным, тогда нет необходимости использовать «friend» в этом примере. Друг используется только тогда, когда требуется предоставление доступа.

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

2 голосов
/ 24 октября 2011

Операторы, в которых левый операнд не является самим классом.Например, cout << somtething может быть достигнуто путем определения функции std::ostream& operator<<(std::ostream& lhs, Something const & rhs); и маркировки их как friend внутри класса.

РЕДАКТИРОВАТЬ: Фриендирование не требуется, никогда.Но это может сделать вещи проще.

1 голос
/ 24 октября 2011

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

Обратите внимание, что в общем случае лучше не объявлять friend s, так как это самое высокое отношение связи в языке, поэтому, когда это возможно, вы должны реализовывать даже свободные перегрузки функций операторов вусловия открытого интерфейса вашего типа (что позволяет вам изменять реализацию типа без необходимости переписывать операторы).В некоторых случаях рекомендуется использовать operatorX как свободную функцию в терминах operatorX=, реализованную как открытую функцию-член (подробнее о перегрузке операторов здесь )

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

template <typename T>
class X {
   int m_data;
public:
   int get_value() const { return m_data; }

   friend std::ostream& operator<<( std::ostream& o, X const & x ) {
      return o << x.get_value();
   }
};

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

1 голос
/ 24 октября 2011

Вам никогда не нужно нужна функция друга. Если вы не хотите, чтобы оператор быть членом (обычно это касается бинарных операторов, которые не изменяют их операнды), нет необходимости, чтобы он был другом. Там однако есть две причины, по которым можно сделать его другом:

  1. для доступа к личным данным членов и
  2. , чтобы определить его в теле класса (даже если это не член), так что ADL найдет его

Вторая причина в основном относится к шаблонам, но обычно определяют операторы, такие как + и - в базовом классе шаблона, в терминах += и -=, так что это наиболее распространенный случай.

1 голос
/ 24 октября 2011

Единственная причина для использования функции друга - доступ к закрытой (в том числе защищенной) переменной-члену и функциям.

0 голосов
/ 22 мая 2013

операторов [] -> =

Должны быть функциями-членами.

Другие бинарные операторы, приемлемые для перегрузки, могут быть записаны в виде функции или в функции memeber-функцииформа.Для перегрузки допустимы все унарные и бинарные операторы C ++, кроме

:.:: sizeof typeid?

0 голосов
/ 24 октября 2011

Вам необходимо использовать функцию друга, когда this не является левой стороной, или, в качестве альтернативы, где this необходимо неявно преобразовать.

Редактировать: И, конечно, если вам действительно нужна часть friend, а также часть с бесплатной функцией.

...