Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
С++.docx
Скачиваний:
27
Добавлен:
10.06.2015
Размер:
95.05 Кб
Скачать

54. Перегрузка операции присваивания. Особенности работы с ресурсоемкими объектами.

Операция присваивания вызывается всегда, когда одному существующему объекту присваивается значение другого. Перегруженная операция присваивается по умолчанию для классов, в объектах которого не предусмотрен динамический захват. В этом случае функция операции определяется компилятором как поэлементное копирование объектов. Если объект ресурсоемкий, то перегрузку можно определить явно при определении класса. В отличие от большинства других бинарных операций функция операции присваивания может быть определена только как метод класса, при этом для сохранения семантики присваивания эта функция операции должна иметь 1 аргумент, а именно ссылку на объект, значение которого присваивается, в возвращать она должна ссылку на объект от имени которого она вызвана.

Рассмотрим пример присваивания для объектов TTochka_v_pole при условии, что это ресурсоемкий класс, рассмотрим ситуацию, когда поэлементное копирование предусмотренное по умолчанию может оказаться неприемлемым по логике алгоритма => если класс не ресурсоемкий, то операцию присваиванию нужно определять явно.

Добавим в класс TTochka_v_pole перегруженную операцию присваивания (=)

const TTochka_v_pole & operator = (const TTochka_v_pole &); // (1)

Замечание:

const применять не обязательно, но целесообразно

Прежде чем провести полное определение отметим особенности работы с объектами класса TTochka_v_pole. В начале разберемся с динамическим полем. Предположим, что мы должны реализовать следующую логику алгоритма (копируемый объект – «Р»)

  • если копируемый объект имеет имя, то есть для поля указателя Fname1 сформируется динамическая область, где хранится строка (имя), то мы должны передать его объекту в который копируется, то есть возникнет новый объект

  • возможны 2 варианта:

  1. в объекте, куда копируется, динамическое поле для хранения уже создано, тогда его нужно уничтожить, так как оно может не подойти по длине, далее создаем новое и закладываем в него имя объекта P

  2. в объекте, куда копируется, динамическое поле еще не создано, тогда его нужно создать и заложить копией имени объекта P

  • если у копируемого объекта имени нет, то возможно 2 варианта действий:

  1. в объекте, куда крпируется, динамическое поле создано, тогда его нужно уничтожить, а полю указателю передать нулевое значение

  2. в объекте, куда копирется, динамическое поле еще не создано, тгда делать ничего не нужно, но для страховки это поле можно еще раз обнулить

Таким образом, старое имя копирующего объекта нужно уничтожить. Почти все остальные поля обрабатываются простым копированием при помощи присваивания, однако, 2 статических поля-счетчика FCeunter и FLivePoint и обычное поле Fnum требуют особого обращения. Так как поля FCeunter и FLivePoint статические, и по логике алгоритма они при создании любого объекта автоматически обновляются (это делает конструктор), поэтому нет смысла их копировать. Обращаются к ним по имени объекта P. Что касается поля Fnum, в его обработку можно закладывать разную логику. Мы будем полагать, что 2-й объект должен быть полной копией P, но при этом он должен сохранить свой отличный номер, а это означает, что осуществлять копирование поля Fnum не нужно. Именно это иллюстрирует тот факт, что автоматически созданная функция операции присваивания может не соответствовать логике алгоритма, даже если в объекте нет динамически созданных полей.

Таким образом определенная вне класса перегруженная операция присваивания будет иметь вид:

const TTochka_v_pole & TTochka_v_pole:: operator = (const TTochka_v_pole & p) { // (2)

if (&P == this) return *this; // (3) удаление лишних действий при самоприсваивании

Работа с динамическим полем:

if (Fname1) delete [ ] Fname1; // (4) уничтожаем имя (если существует) копируемого объекта

if (P.Fname1) // (5) у копируемого объекта есть имя

{Fname1 = new char [strlen (P.Fname1_ +]; // (6) тогда у копирующегося создается динамическое поле

strcpy (Fname1, P.Fname1);} // (7) и копируем в него имя объекта P

else Fname1 = 0; // (8)

Далее работаем с остольными полями (за исключением полей FCeunter, FLivePoint и Fnum):

for (int i=0; I <3; i++) {FRO [i] = P.FRO [i]; FVO [i] = P.FVO [i];} // (9)

-//-//-//-//-//-//-//-//-//- {Vmin Vmax [i] [0] = P.Vmin Vmax [i] [0]; // (10)

-//-//-//-//-//-//-//-//-//-//-//-//-//-//- [i] [1] -//-//-//-//-//- [i] [1]

FMp = P.Mp; // (12)

FMeolor = P.Fmeolor // (13)

Fg = P.Fg // (14)

for (int i=o; I < 20; i++) {… Fname2 [i] …} // (15)

return *this; // (20)

} // (21)

Point4 = Point2; // (22)

К любой функции операции можно обратиться явно, как к любой обычной функции, например так:

Point4.operator = (Point2); // (22’)

Запрет!!!

Нужно учитывать, что для перегруженных типов “+=” не допустимы.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]