Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 [ 57 ] 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76

some class *p;

c = *(p = &(a + b));

Это даже страшно выговорить. Функция operator+() не может прямо возвратить указатель. Если она выглядит подобным образом:

const some class *some class::operator+( const some class &r )

const

some class *p = new some class; ... return p;

то вы должны записать:

c=*(p=a+b);

что не так страшно, как в предыдущем примере, но все еще довольно плохо. Единственное решение этой задачи состоит в том, чтобы стиснуть зубы и вернуть объект:

const some class some class::operator+( const some class &r )

const

some class obj; ... return obj;

Если вам удастся вызвать конструктор копии в операторе return, то быть по сему.



Часть 8г. Конструкторы, деструкторы и operator=( )

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

Генерируемый компилятором конструктор копии (чьим аргументом является ссылка на текущий класс) нужен еще по двум причинам, кроме таблицы виртуальных функций. Во-первых, код на Си++, который выглядит как Си, должен и работать как Си. Так как правила копирования, которые относятся к классу, относятся также и к структуре, поэтому компилятор будет вынужден обычно генерировать конструктор копии в структуре, чтобы обрабатывать копирование структур в стиле Си. Этот конструктор копии используется явно подобным образом:

some class x; конструктор по умолчанию

some classy=x; конструктор копии

но кроме этого он используется и неявно в двух ситуациях. Первой является вызов по значению:

some class x;

f( some classx) передается по значению, а не по ссылке.

f(x); вызывается конструктор копии для передачи x

по значению. Оно должно скопироваться в стек.

Второй является возврат по значению:

some class g() Помните, что x- локальная, автоматическая переменная.Она исчезает после возвращения функцией значения.

some class x; Оператор return после этого должен return x; скопировать x куда-нибудь в надежное место

} (обычно в стек после аргументов).Он

использует для этой цели конструктор копии.

Генерируемая компилятором функция-операция operator=() нужна лишь для поддержки копирования структур в стиле Си там, где не определена операция присваивания.



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. Тем не



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 [ 57 ] 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76