Ответ 1
Первая форма операторов - это то, что вы определяете внутри класса Type
.
Вторая форма операторов - это то, что вы определяете как свободностоящие функции в том же пространстве имен, что и класс Type
.
Это очень хорошая идея для определения автономных функций, потому что тогда операнды к ним могут участвовать в неявных преобразованиях.
Пример
Предположим, что этот класс:
class Type {
public:
Type(int foo) { }
// Added the const qualifier as an update: see end of answer
Type operator + (const Type& type) const { return *this; }
};
Затем вы можете написать:
Type a = Type(1) + Type(2); // OK
Type b = Type(1) + 2; // Also OK: conversion of int(2) to Type
Но вы не можете писать:
Type c = 1 + Type(2); // DOES NOT COMPILE
Имея operator+
как свободную функцию, также позволяет и последний случай.
То, что вторая форма оператора делает неправильно, заключается в том, что она выполняет добавление путем прямой настройки частных членов своих операндов (я предполагаю, что в противном случае это не обязательно должно быть другом). Это не должно быть так: вместо этого операторы также должны быть определены внутри класса, и автономные функции должны их называть.
Чтобы узнать, как это получится, попросите услуги гуру: http://www.gotw.ca/gotw/004.htm. Прокрутите в самом конце, чтобы увидеть, как реализовать автономные функции.
Update:
Как отмечает Джеймс Макнеллис в своем комментарии, две приведенные формы также имеют другое значение: левая сторона не является const-квалификацией в первой версии. Так как операнды operator+
действительно не должны быть модифицированы как часть добавления, очень хорошая идея, чтобы const-квалифицировать их все время. Класс Type
в моем примере теперь делает это, где изначально этого не было.
Заключение
Лучший способ справиться с операторами +
и +=
:
- Определите
operator+=
какT& T::operator+=(const T&);
внутри вашего класса. Здесь будет добавлено дополнение. - Определите
operator+
какT T::operator+(const T&) const;
внутри вашего класса. Этот оператор будет реализован в терминах предыдущего. - Предоставьте бесплатную функцию
T operator+(const T&, const T&);
вне класса, но внутри одного и того же пространства имен. Эта функция вызовет элементoperator+
для выполнения этой работы.
Вы можете опустить шаг 2 и напрямую запросить функцию T::operator+=
, но в качестве личного предпочтения я хочу сохранить всю логику добавления внутри класса.