Язык программирования C++.

14.4. Операторы присвоения.

Кроме операторов присвоения копии и присваивания при перемещении, которые присваивают один объект типа класса другому объекту того же класса (см. раздел 13.1.2 и раздел 13.6.2), в классе можно определить дополнительные операторы присвоения, позволяющие использовать в качестве правого операнда другие типы.

Например, библиотечный класс vector, кроме операторов присвоения копии и присваивания при перемещении, определяет третий оператор присвоения, получающий заключенный в фигурные скобки список элементов (см. раздел 9.2.5). Этот оператор можно использовать следующим образом:

vector<string> v;

v = {"a", "an", "the"};

Такой оператор можно также добавить в класс StrVec (см. раздел 13.5):

class StrVec {

public:

 StrVec &operator=(std::initializer_list<std::string>);

 // другие члены, как в разделе 13.5

}

Чтобы не отличаться от операторов присвоения для встроенных типов (и уже определенных операторов присвоения копии и присваивания при перемещении), новый оператор присвоения будет возвращать ссылку на левый операнд:

StrVec &StrVec::operator=(initializer_list<string> il) {

 // alloc_n_copy() резервирует пространство и копирует элементы

 // из заданного диапазона

 auto data = alloc_n_copy(il.begin(), il.end());

 free(); // удалить элементы в этом объекте и освободить пространство

 elements = data.first; // обновить переменные-члены, чтобы указывать

                        // на новое пространство

 first_free = cap = data.second;

 return *this;

}

Подобно операторам присвоения копии и присваивания при перемещении, другие перегруженные операторы присвоения должны освобождать существующие элементы и создавать новые. В отличие от операторов копирования и присваивания при перемещении, этот оператор не должен проверять случай присвоения себя себе. Параметр имеет тип initializer_list<string> (см. раздел 6.2.6), а это означает, что объект il не может быть тем же объектом, на который указывает указатель this.

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

Составные операторы присвоения.

Составные операторы присвоения не обязаны быть функциями-членами. Однако все операторы присвоения, включая составные, предпочтительно определять в классе. Для согласованности со встроенными составными операторами присвоения эти операторы должны возвращать ссылку на левый операнд. Например, ниже приведено определение составного оператора присвоения для класса Sales_data.

// бинарный оператор-член:

// левый операнд связан с неявным указателем this

// подразумевается, что оба объекта относятся к той же книге

Sales_data& Sales_data::operator+=(const Sales_data &rhs) {

 units_sold += rhs.units_sold;

 revenue += rhs.revenue;

 return *this;

}

Язык программирования C++.Обычно операторы присвоения и составные операторы присвоения должны быть определены как функции-члены и возвращать ссылку на левый операнд.

Упражнения раздела 14.4.

Упражнение 14.20. Определите оператор суммы и составной оператор присвоения для класса Sales_data.

Упражнение 14.21. Напишите операторы класса Sales_data так, чтобы + осуществлял сложение, а оператор  += вызывал оператор  +. Обсудите недостатки этого подхода по сравнению со способом, которым эти операторы были определены в разделах 14.3 и 14.4.

Упражнение 14.22. Определите версию оператора присвоения, способного присвоить строку, представляющую ISBN, объекту класса Sales_data.

Упражнение 14.23. Определите в версии класса StrVec оператор присвоения для типа initializer_list.

Упражнение 14.24. Примите решение, нуждается ли класс из упражнения 7.40 раздела 7.5.1 в операторах копирования и присваивания при перемещении. Если да, то определите эти операторы.

Упражнение 14.25. Реализуйте все остальные операторы присвоения, которые должен определить класс. Объясните, какие типы должны использоваться как операнды и почему.