Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
С++ Семинар №1.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
257.02 Кб
Скачать

Перегрузка операций инкремента

Операция инкремента имеет две формы: префиксную и постфиксную. Для первой

формы сначала изменяется состояние объекта в соответствии с данной операцией,

а затем он (объект) используется в том или ином выражении. Для второй

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

операции, а потом уже его состояние изменяется.

Чтобы компилятор смог различить эти две формы операции инкремента, для

них используются разные сигнатуры, например:

Po1nt& operator ++(): // префиксный инкремент

Point o^^er^tor ++(1nt); // постфиксный инкремент

Покажем реализацию данных операций на примере класса Point:

Po1nt& Point::operator ++() {

X++ ; y+4-;

return 4h1s:

}

Point Point::operator ++(1nt) {

Point old = 4h1s;

X++; У++;

return old:

}

Обратите внимание, что в префиксной операции осуществляется возврат результата

по ссылке. Это предотвращает вызов конструктора копирования для создания

возвращаемого значения и последующего вызова деструктора. В постфиксной

операции инкремента возврат по ссылке не подходит, поскольку необходимо

вернуть первоначальное состояние объекта, сохраненное в локальной перемен-

Задача 1.1. Поиск в массиве структур 31

ной old. Таким образом, префиксный инкремент является более эффективной

операцией, чем постфиксный инкремент.

Заметим, что ранее мы не обращали внимания на запись инкремента в заголовке

цикла for. Так, в первой книге практикума во всех примерах использовалась

постфиксная форма инкремента: for (1 = 0: 1 < п; 1++). Дело в том, что пока параметр

1 Является переменной встроенного типа, форма инкремента безразлична:

программа будет работать одинаково. Ситуация меняется, если параметр 1

есть объект некоторого класса — в этом случае префиксная форма инкремента

оказывается более эффективной. Когда мы будем использовать контейнерные

классы стандартной библиотеки, параметр 1 в заголовке цикла очень часто будет

представлять объект-итератор.

СОВЕТ

Всегда используйте префиксный инкремент для параметра цикла for — это дает более

эффективный программный код.

ПРИМЕЧАНИЕ

Все сказанное о данной операции относится также и к операции декремента.

Перегрузка операции присваивания

о перегрузке этой операции следует поговорить особо по нескольким причинам.

Во-первых, если вы не определите эту операцию в некотором классе, то компилятор

создаст операцию присваивания по умолчанию, которая выполняет поэлементное

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

которые возникают при использовании конструктора копирования по

умолчанию (см. выше). Поэтому запомните золотое правило: если в классе требуется

определить конструктор копирования, то его верной спутницей должна

быть перегруженная операция присваивания, и наоборот.

Во-вторых, операция присваивания может быть определена только в форме метода

класса.

В-третьих, операция присваивания не наследуется (в отличие от всех остальных

операций).

Например, для класса Man из задачи 1,1 перегрузку операции присваивания можно

определить следующим образом:

// Man.h (интерфейс класса)

class Man {

public:

// . . .

Man& operator =(const Man&): // операция присваивания

private:

char* pName:

// . . .

}:

3 2 Семинар 1. Классы

// Мап.срр (реализация класса)

// . . .

Мап8( Man: :operator =(const Man& man) {

if (this == &man) return 4h1s; // проверка на самоприсваивание

delete [] pName: // уничтожить предыдущее значение

pName = new char[strlen(man.pName) + 1];

strcpyCpName. man.pName);

birth_year = man.b1rth_year:

pay = man.pay;

return 4 h i s:

}

Обратите внимание на несколько простых, но важных моментов при реализации

операции присваивания:

• убедитесь, что не выполняется присваивание вида х = х. Если левая и правая

части ссылаются на один и тот же объект, то делать ничего не надо. Если не

перехватить этот особый случай, то следующий шаг уничтожит значение, на

которое указывает pName, еще до того, как оно будет скопировано;

• удалите предыдущие значения полей в динамически выделенной памяти;

• выделите память под новые значения полей;

• скопируйте в нее новые значения всех полей;

• возвратите значение объекта, на которое указывает this (то есть 4h1s).

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