Упражнение 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. Реализуйте все остальные операторы присвоения, которые должен определить класс. Объясните, какие типы должны использоваться как операнды и почему.
14.5. Оператор индексирования
Классы, представляющие контейнеры, способные возвращать элементы по позиции, зачастую определяют оператор индексирования operator[].
Согласно общепринятому смыслу индексирования, оператор индексирования обычно возвращает ссылку на выбранный элемент. Возвращающий ссылку оператор индексирования применим с обеих сторон оператора присвоения. Следовательно, имеет смысл определить и константную, и неконстантную версии этого оператора. При применении к константному объекту оператор индексирования должен возвращать ссылку на константу, чтобы предотвратить присвоение возвращенному объекту.
В качестве примера определим оператор индексирования для класса StrVec (см. раздел 13.5):
class StrVec {
public:
std::string& operator[](std::size_t n)
{ return elements[n]; }
const std::string& operator[](std::size_t n) const
{ return elements[n]; }
//
private:
std::string *elements; //
};
Эти операторы можно использовать таким же образом, как и индексирование вектора или массива. Поскольку оператор индексирования возвращает ссылку на элемент, если объект класса StrVec не константен, то этому элементу можно присвоить значение; если индексируется константный объект, присвоение невозможно:
//
const StrVec cvec = svec; //
//
//
if (svec.size() && svec[0].empty()) {
svec[0] = "zero"; //
cvec[0] = "Zip"; //
//
}
Упражнение 14.26. Определите операторы индексирования для классов StrVec, String, StrBlob и StrBlobPtr.
14.6. Операторы инкремента и декремента
Операторы инкремента (++) и декремента (--) обычно реализуют для классов итераторов. Эти операторы позволяют перемещать итератор с элемента на элемент последовательности. Язык никак не требует, чтобы эти операторы были членами класса. Но поскольку они изменяют состояние объекта, с которым работают, лучше сделать их членами класса.
Для встроенных типов есть префиксные и постфиксные версии операторов инкремента и декремента. Ничего удивительного, что для собственных классов также можно определить префиксные и постфиксные версии этих операторов. Давайте сначала рассмотрим префиксные версии, а затем реализуем постфиксные.
Для иллюстрации операторов инкремента и декремента определим их для класса StrBlobPtr (см. раздел 12.1.6):
class StrBlobPtr {
public:
//