Преимущества перегрузки + = или — = операторы

Недавно я выполнил задание по перегрузке основных функционалистов (+, -, сопряженных …) сложного класса с помощью шаблонов. Мне пришлось немного потеть, чтобы найти правильный тип возвращаемого значения (приведение к более высокому типу), но в конце я все заработало отлично.
Вот так выглядит мой класс —

template <typename T> class complex_t
{
private:
T real;
T imaginary;

public:

complex_t(T X, T Y)
{
real=X;
imaginary=Y;
}
}

Но я не получил полную оценку, потому что я не реализовал операторы + =, — = и т. Д. Почему важно реализовать эти операторы? Делает ли это действительно какие-то конкретные преимущества?
Кто-нибудь может поделиться некоторыми мыслями?

Заранее спасибо,

5

Решение

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

В качестве примера предположим, что вы реализуете векторы в математическом смысле, поддерживая произвольные длины.

class Vector
{
std::vector<double> elements;

public:
Vector operator+(double x)
{
// must return a copy!
Vector v(*this);
for (size_t i=0; i < elements.size(); i++)
v.elements[i] += x;
return v;
}

Vector &operator+=(double x)
{
// in-place operation
for (size_t i=0; i < elements.size(); i++)
elements[i] += x;
return *this;
}
};
6

Другие решения

Если у вас есть два объекта, A и B, и вы хотите увеличить A на B, без operator+=, вы бы сделали это:

A = A + B;

В обычных реализациях это будет связано с созданием третьего (временного) объекта, который затем копируется обратно в A. Однако с operator+=, A может быть изменен на месте, так что это обычно менее трудоемко и, следовательно, более эффективно.

Возможно, еще важнее то, что это идиоматично для языка. Программисты C ++ ожидают, что если они смогут сделать это:

A = A + B;

Они также могут сделать это:

A += B;
9

Оператор перегрузки — позволяет пользователям вашего класса «Foo» писать код наподобие:

Foo f1 = ...;
Foo f2 = ...;
f2 = f2 - f1;

Оператор перегрузки — = позволяет пользователям писать

Foo f1 = ...;
Foo f2 = ...;

f2 -= f1;

Если вы не перегружаете — =, второй пример просто не сработает, что, вероятно, ожидают от ваших пользователей.

Изменить, чтобы включить точку эффективности (Мой ответ получает голосование против, поэтому я решил обобщить повторяющиеся моменты из других ответов, чтобы сохранить все детали в одном месте. Благодарность Ларсмансу и Бенджамину)

f2 -= f1 часто более эффективен, чем f2 = f2 - f1 по двум причинам:

  • operator - нужно взять копию thisперед изменением копии и ее возвратом.
  • operator - также должен возвращать результат по значению (он не может вернуть ссылку на объект стека), возможно, вызывая вторую копию.

operator -= с другой стороны, модифицирует this на месте, поэтому не делает никаких копий.

9

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

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

5

Потому что так работают встроенные операторы. В любое время у вас есть
бинарный оператор opесть вариант
op= такой, что a op= b; это
эквивалент a = a op b;, Кроме этого a только
оценивается один раз. Если вы определяете перегруженные операторы, вы должны
моделировать их поведение на встроенных операторах (и, если поведение
не может быть естественным образом на встроенных операторов, вы не должны быть
перегрузки). обеспечение +, но не предоставляя +=, о как
обеспечение <, но не предоставляя <=,

На практике обычным способом реализации арифметических операторов является
определить только op= операторы в классе, а затем
извлечь из экземпляра шаблона класса, который определяет
op операторы, использующие op=
операторы, что-то вроде:

class MyType : public BinaryOperators<MyType>
{
public:
MyType& operator+=( MyType const& other );
//  ...
};

где BinaryOperators выглядит примерно так:

template <typename ValueType>
class BinaryOperators
{
friend ValueType
operator+( ValueType const& lhs, ValueType const& rhs )
{
ValueType results( lhs );
results += rhs;
return results;
}
//  ...
};

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

4

Оператор + по своей конструкции будет выделять и создавать совершенно новый объект, а оператор + = может изменять существующий объект. Это позволяет вам реализовать оператор + = гораздо эффективнее, чем то, что происходит, когда пользователь заменяет его на val1 = val1 + val2,

Кроме того, когда я знаю, что класс перегружает +, я также ожидаю, что он перегружает + =.

3

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

MyModifiedInteger extends Integer {
private boolean bigNumberFlag = false;
...
@Override
public void +=(int i) {
this = this + i;
if (this > 100) {
this.bigNumberFlag = true;
}
}
}
MyModifiedInteger myModifiedInt = new MyModifiedInteger();
List<Integer> integers = new ArrayList<Integer>();
integers.add(myModifiedInt);
for (Integer i : integers) {
i+=5;
}

Идея здесь (если я правильно применил свое наследование Java) состоит в том, чтобы использовать оператор + = для моих целых чисел, а также наследующие классы, которые могут по-разному обрабатывать операцию + =.

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector