Первая форма операторов - это то, что вы определяете внутри класса 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. Прокрутите в самом конце, чтобы увидеть, как реализовать автономные функции.
Обновление:
Как отмечает Джеймс МакНеллис в своем комментарии, две приведенные формы также имеют другое отличие: левая часть не является константной в первой версии. Так как операнды operator+
не должны быть изменены как часть сложения, очень хорошая идея постоянно их квалифицировать. Класс Type
в моем примере теперь делает это, где изначально этого не было.
Заключение
Лучший способ справиться с операторами +
и +=
:
- Определите
operator+=
как T& T::operator+=(const T&);
в вашем классе. Здесь будет реализовано дополнение.
- Определите
operator+
как T T::operator+(const T&) const;
внутри вашего класса. Этот оператор будет реализован в терминах предыдущего.
- Предоставляет свободную функцию
T operator+(const T&, const T&);
вне класса, но внутри того же пространства имен. Эта функция будет вызывать члена operator+
для выполнения работы.
Вы можете пропустить шаг 2 и получить бесплатный вызов функции T::operator+=
напрямую, но, исходя из личных предпочтений, я хотел бы сохранить всю логику сложения внутри класса.