Скачиваний:
316
Добавлен:
28.03.2021
Размер:
378.53 Кб
Скачать

29. Аргументы перегружаемого оператора. Значения, возвращаемые перегружаемым оператором. Временные безымянные объекты.

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

Тип возвращаемого значения зависит от сути оператора. Если оператор должен возвращать новое значение, то необходимо создавать новый объект (как в случае бинарного плюса). Если вы хотите запретить изменение объекта, то нужно возвращать его константным.

Для операторов присваивания необходимо возвращать ссылку на измененный элемент. Также, если вы хотите использовать оператор присваивания в конструкциях вида (x=y).f(), где функция f() вызывается для переменной x, после присваивания ей y, то не возвращайте ссылку на константу, возвращайте просто ссылку. Логические операторы должны возвращать в худшем случае int, а в лучшем bool.

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

30. Перегрузка постфиксных операторов. Перегрузка оператора ()

Стандарт языка С++ позволяет явно создать отдельные версии префиксного и постфиксного операторов инкрементации и декрементации. Для этого следует определить две версии функции operator++(). Если символы ++ предшествуют операндам, вызывается операторная функция operator++(), если символы ++ следуют за операндами, вызывается операторная функция operator++(int x). Постфиксный оператор инкрементации: operator++(int x){}

three_d three_d::operator++ (int notused)

{

three_d temp = *this; // сохранение исходного значения

x++; // инкремент координат х, у и z

y++;

z++;

return temp; // возврат исходного значения

}

Оператор "()" (оператор вызова функций). При его перегрузке создается не новый способ вызова функций, а операторная функция, которой можно передать произвольное число параметров.

Предположим, что некоторый класс содержит следующее объявление перегруженной операторной функции. int operator()(float f, char *p); И если в программе создается объект ob этого класса, то инструкция ob (99.57, "перегрузка"); преобразуется в следующий вызов операторной функции operator(): operator() (99.57, "перегрузка");

В общем случае при перегрузке оператора "()" определяются параметры, которые необходимо передать функции operator(). При использовании оператора "()" в программе задаваемые при этом аргументы копируются в эти параметры. Как всегда, объект, который генерирует вызов операторной функции (ob в данном примере), адресуется указателем this.

31. Перегрузка арифметических операторов. Перегрузка операций ++ и – –

Перегруженный оператор (в своем новом качестве) работает как совершенно новый оператор. Функция operator может быть использована для расширения области приложения следующих операторов: +, -, *, %, &, | и т.д. Операторы, которые не могут быть перегружены: «.», «.*», «::», «?:», sizeof и typeid. Для перегрузки оператора разрабатываются функции, являющиеся либо компонентами, либо friend-функциями того класса, для которого они используются.

Общий формат функции operator: тип имя_класса::operator#(список_аргументов) { операция_над_классом }

Перегружаемый оператор обозначается символом "#". Операторная функция может быть членом класса или не быть им. Операторные функции, не являющиеся членами класса, часто определяются как его "друзья". Операторные функции-члены и функции-не члены класса различаются по форме перегрузке.

Можно также перегружать такие унарные операторы, как "++", "--", или унарные "-" и "+". При перегрузке унарного оператора с помощью функции-члена операторной функции ни один объект не передается явным образом. Операция же выполняется над объектом, который генерирует вызов этой функции через неявно переданный указатель this. (three_d operator++(); // определение в классе) Перегруженная префиксная версия оператора "++":

three_d three_d::operator++() {

х++; у++; z++; // инкремент координат х, у и z

return *this; }

Как отмечено в комментариях к предыдущей программе, функция operator++() определяет префиксную форму оператора "++" для класса three_d. Но нам ничего не мешает перегрузить и постфиксную форму. Прототип постфиксной формы оператора "++" для класса three_d имеет следующий вид.

three_d three_d::operator++(int notused);

Операторы инкремента и декремента имеют как префиксную, так и постфиксную формы. Параметр notused не используется самой функцией. Он служит индикатором для компилятора, позволяющим отличить префиксную форму оператора инкремента от постфиксной. Перегрузка постфиксной версии оператора "++":

three_d three_d::operator++(int notused) {

three_d temp = *this; // сохранение исходного значения

x++; у++; z++;// инкремент координат х, у и z

return temp; // возврат исходного значения }

Обратите внимание на то, что эта функция сохраняет текущее значение операнда путем выполнения такой инструкции. three_d temp = *this; Сохраненное значение операнда (в объекте temp) возвращается с помощью инструкции return. Следует иметь в виду, что традиционный постфиксный оператор инкремента сначала получает значение операнда, а затем его инкрементирует. Следовательно, прежде чем инкрементировать текущее значение операнда, его нужно сохранить, а затем и возвратить (не забывайте, что постфиксный оператор инкремента не должен возвращать модифицированное значение своего операнда).

32 Перегрузка оператора []. Перегрузка оператора ->.

Его можно перегружать только для класса и только с использованием функции-члена. Вот как выглядит общий формат операторной функции-члена operator[]().

тип имя_класса::operator[](int индекс) { // ... } Оператор "[]" перегружается как бинарный оператор.

Формально параметр индекс необязательно должен иметь тип int, но операторные функции operator[]() обычно используются для обеспечения индексации массивов. Предположим, у нас определен объект ob, тогда выражение ob[3] преобразуется в следующий вызов операторной функции operator[](): ob.operator[](3) Другими словами, значение выражения, заданного в операторе индексации, передается операторной функции operator[]() в качестве явно заданного аргумента. При этом указатель this будет указывать на объект ob, т.е. объект, который генерирует вызов этой функции

Можно разработать операторную функцию operator[]() так, чтобы оператор "[]" можно было использовать как слева, так и справа от оператора присваивания. Для этого достаточно указать, что значение, возвращаемое операторной функцией operator[](), является ссылкой. Пример: