перегрузка оператора (функция друга и члена) - PullRequest
9 голосов
/ 05 мая 2010

В чем разница между перегрузкой операторов с использованием ключевого слова friend и функцией-членом внутри класса?

Кроме того, в чем разница в случае перегрузки любого унарного оператора (т. Е. В качестве друга по сравнению с функцией-членом)?

Ответы [ 5 ]

12 голосов
/ 05 мая 2010

Джейкоб прав: функция, объявленная в классе friend, имеет доступ к этому классу, но вообще не находится внутри класса, и все остальные имеют к нему доступ.

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

Неявный аргумент отличается от первого аргумента свободной функцией несколькими способами:

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

Ситуация такая же для унарных, двоичных или n-арных (в случае operator()).

Члены привилегии мутации: Операторы, которые изменяют первый операнд (например, +=, =, префикс ++), должны быть реализованы в качестве функций-членов и должны реализовывать только внутренности всех перегрузки. Постфикс ++ - гражданин второго сорта; это реализовано как Obj ret = *this; ++ this; return ret;. Обратите внимание, что это иногда распространяется на конструкторы копирования, которые могут содержать *this = initializer.

Правило свободы для пассажиров: Только коммутативные операторы (например, /) должны быть свободными функциями; все остальные операторы (например, унарные все) должны быть членами. Коммутативные операторы по своей сути делают копию объекта; они реализованы как Obj ret = lhs; ret @= rhs; return ret;, где @ - коммутативный оператор, а lhs и rhs - аргументы левой и правой стороны соответственно.

Золотое правило дружбы на С ++: Избегайте дружбы. friend загрязняет семантику дизайна. Следствие перегрузки: Перегрузка проста, если вы следуете приведенным выше правилам, тогда friend безвреден. friend Определение определения перегрузки шаблонов позволяет размещать их в скобках class {.

Обратите внимание, что некоторые операторы не могут быть свободными функциями: =, ->, [] и (), потому что в стандарте это специально указано в разделе 13.5. Я думаю, что это все ... я думал, что унарные & и * тоже, но я был явно неправ. Они должны всегда перегружаться как члены, и только после тщательного обдумывания!

3 голосов
/ 05 мая 2010

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

1 голос
/ 11 августа 2012

Функция-член требует, чтобы левый оператор был того же типа. Функция друга может разрешить неявное приведение к левому оператору.

1 голос
/ 05 мая 2010

Функция-член требует, чтобы левый оператор был того же типа. Функция друга может разрешить неявное приведение к левому оператору.

Например, допустим, мы создали класс BigInt. И мы создаем оператор функции-члена +, чтобы взять оператор правой руки BigInt.

Теперь давайте также скажем, что BigInt имеет конструктор, который принимает обычный int. Этот конструктор НЕ является явным (явное ключевое слово) и принимает один параметр. Это означает, что C ++ может легко преобразовать из int в BigInt.

Когда у нас есть эти вещи, мы можем сделать это:

BigInt foo (5); Бар BigInt; bar = foo + 5;

Но мы НЕ МОЖЕМ сделать это:

BigInt foo (5) Бар BigInt; bar = 5 + foo;

Однако, если бы мы использовали функцию друга вместо функции-члена, тогда оба будут работать.

0 голосов
/ 05 мая 2010

Функции-члены могут вызываться по rvalue, тогда как свободные функции, принимающие ссылки на неконстантные, не могут вызываться с rvalue. Например, ++function_returning_iterator_by_value() компилируется, только если вы внедрили operator++ в качестве члена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...