Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OOP.doc
Скачиваний:
7
Добавлен:
25.04.2019
Размер:
1.34 Mб
Скачать

Return fail();

}

Особый случай при перегрузке унарных операций составляют операции инкремента и декремента (++ и ––). Особенность их перегрузки состоит в том, что они кроме префиксной имеют еще и постфиксную форму, и необходимо обеспечить четкое различие этих форм при вызове. Для того чтобы этого добиться, стандарт предусматривает определение постфиксных форм с дополнительным фиктивным параметром типа int. При определении функции operator++ (или operator––) внутри класса она не должна иметь параметров, если ее форма префиксная, и должна иметь параметр типа int в постфиксной форме. Если же operator++ (или operator––) определяется за пределами класса, то она должна иметь один параметр в префиксной форме и два параметра, второй из которых типа int, – в постфиксной форме. Чтобы пояснить все сказанное, ниже дается пример определения функции operator++ в разных вариантах28:

class X {

public:

...

// компонентные функции-операции

X & operator ++(); // префиксная форма

const X operator ++(int); // постфиксная форма

...

};

class Y {

...

};

// глобальные функции-операции

Y & operator ++(Y &); // префиксная форма

const Y operator ++(Y &, int); // постфиксная форма

При вызове функции operator++ (operator––) используется один из четырех возможных вариантов:

void SomeFunction(X & a, Y & b) {

++a; // вызывается a.operator ++()

a++; // вызывается a.operator ++(0)

++b; // вызывается operator ++(b)

b++; // вызывается operator ++(b,0)

}

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

Кроме проблемы различия префиксной и постфиксной форм при вызове, перегрузка операций ++ и –– имеет и другие особенности. Например, как правильно задать возвращаемые значение? Как показывает анализ, наиболее подходящий вариант такой: для префиксной формы – ссылка на объект, а для постфиксной – константный объект. Действительно, префиксная операция ++ (и ––) должна изменить объект-операнд (*this или первый аргумент) и возвратить его же в измененном виде. Постфиксная операция ++ (––) должна изменить операнд, но вернуть его старое значение. Константность возвращаемому объекту необходимо придать для того, чтобы не дать программисту делать «глупости» вида X++ = Y или X++++.

Из соображений эффективности и гибкости обычно постфиксную форму operator++ (––) реализуют на основе префиксной формы с тем, чтобы в будущем поддерживать только префиксную30. Ниже дано определение функции operator++(int), реализованной через operator++():

const X X::operator ++(int)

{

X old(*this); // запомнить старый объект

++*this; // изменить объект, вызывая operator++()

return old; // вернуть старый объект

}

И еще один момент, касающийся перегрузки унарных операций. Он связан с операцией преобразования типа в стиле С31.

Операция преобразования типа рассматривается как унарная операция и может быть определена только как нестатическая компонентная функция-операция без параметров. Формат записи ее прототипа имеет вид:

operator type() const;

где вместо type может быть подставлен идентификатор или декларация любого типа: например, char* или CAnotherClass. Как видно из формата, функция-операция не содержит типа возвращаемого значения – он и не нужен, так как явно выводится по type.

Приведем несколько примеров:

operator const char * () const;

operator int () const;

operator CAnotherClass () const;

Основная проблема, связанная с пользовательскими функциями-операциями преобразования типов, заключается в том, что они могут вызываться неявно, причем тогда, когда их вызов не входит в замысел программиста. Выход из этой ситуации – создавать обычные компонентные функции преобразования. В результате неявные преобразования становятся невозможными. Например, именно по этой причине в стандартном шаблонном классе basic_string вместо функции-операции operator char * содержится обычная компонентная функция c_str, выполняющая явное преобразование строки типа string в классическую строку char * (более точно, в строку const char *). Аналогичная функция есть в классе AnsiString, представляющем строки однобайтных символов в среде Borland C++ Builder32.

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