Страница 40 из 74 124. Операция operator=( ) должна возвращать ссылку на константу. 125. Присваивание самому себе должно работать. Определение operator=( ) должно всегда иметь следующую форму: class class_name { const class_name ?operator=( const class_name ?r );}; const class_name ?class_name::operator=( const class_name ?r ) { if( this != ?r ) { // здесь скопировать} return *this; } Аргумент, представляющий операнд источника данных, является ссылкой, чтобы избежать накладных расходов вызова по значению; это ссылка на константу, потому что аргумент не предназначен для модификации. Эта функция возвращает ссылку, потому что она может это сделать. То есть вы могли бы удалить ? из объявления возвращаемой величины, и все бы работало прекрасно, но вы бы получили ненужный вызов конструктора копии, вынужденный возвратом по значению. Так как у нас уже есть объект, инициализированный по типу правой части (*this), то мы просто можем его вернуть. Даже если возврат объекта вместо ссылки в действительности является ошибкой для функции operator=(), компилятор просто выполнит то, что вы ему приказали. Здесь не будет сообщения об ошибке; и на самом деле все будет работать. Код просто будет выполняться более медленно, чем нужно. Наконец, operator=() должен возвращать ссылку на константу просто потому, что не хотите, чтобы кто-нибудь имел возможность модифицировать возвращенный объект после того, как произошло присваивание. Следующее будет недопустимым в случае возврата ссылки на константу: (x =y) = z;Причина состоит в том, что (x=y) расценивается как возвращаемое значение функции operator=(), т.е. константная ссылка. Получателем сообщения =z является объект, только что возвращенный от x=y. Тем не менее, вы не можете послать сообщение operator=() константному объекту, потому что его объявление не имеет в конце const: // НЕ ДЕЛАЙТЕ ЭТОГО // В ФУНКЦИИ С ИСПОЛЬЗОВАНИЕМ // operator=(). // | // V const class_name ?operator=( const class_name ?r ) const;Компилятор должен выдать вам ошибку типа "не могу преобразовать ссылку на переменную в ссылку на константу", если вы попробуете (x=y)=z. Другим спорным моментом в предыдущем коде является сравнение: if( this != ?r )в функции operator=(). Выражение: class_name x; // ... x = x; должно всегда срабатывать, и сравнение this с адресом входного правого аргумента является простым способом в этом убедиться. Имейте в виду, что многие алгоритмы полагают самоприсваивание безвредным, поэтому не делайте его особым случаем. Также имейте в виду, что самоприсваивание могло бы быть затушевано при помощи указателя как в: class_name array[10]; class_name *p = array; // ... *p = array[0]; |