Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шпора 57стр.doc
Скачиваний:
54
Добавлен:
15.06.2014
Размер:
478.21 Кб
Скачать

Вопрос 15. Перегрузка операций ввода/вывода в поток, бинар и унар операций.

С++ способен вводить и выводить стандартные типы данных, используя операцию поместить в поток » и операцию взять из потока «. Эти операции уже перегружены в библиотеках классов, которыми снабжены компиляторы С++, чтобы обрабатывать каждый стандартный тип данных, включая строки и адреса памяти. Операции поместить в поток и взять из потока можно также перегрузить для того, чтобы выполнять ввод и вывод типов, опреде­ленных пользователем. Ф-ция-операция взять из потока (operator>>) получает как аргументы ссылку input типа istream, и ссылку, названную num, на определенный пользователем тип PhoneNumber; ф-ция возвращает ссылку типа istream. Когда компилятор видит выражение

cin » phone в main, он генерирует вызов функции operator>>(cin, phone);

Операция поместить в поток получает как аргументы ссылку output типа ostream и ссылку num на определенный пользователем тип PhoneNumber и возвращает ссылку типа ostream. Функция operator<< выводит на экран объекты типа PhoneNumber. Когда компилятор видит выражение

cout « phone в main, он генерирует вызов функции operator<<(cout, phone);

Ф-ции operator>> и operator<< объявлены в class PhoneNumber не как ф-ции-эл-ты, а как дружественные ф-ции. Эти операции не могут быть Эл-тами, т.к. объект класса PhoneNumber появляется в каждом случае как правый операнд операции; а для перегру­женной операции, записанной как ф-ция-эл-т, операнд класса должен появляться слева. Перегруженные операции поместить в поток и взять из потока должны объявляться как дружественные, если они должны иметь прямой доступ к закрытым элементам класса.

Перегрузка унарных операций

Унарную операцию класса можно перегружать как нестатическую ф-цию-эл-т без аргументов, либо как ф-цию, не явл-ся Эл-том, с одним аргументом; этот аргумент д. б. либо объектом класса, либо ссылкой на объект класса. Ф-ции-эл-ты, к-ые реализуют перегру­женные операции, д. б. нестатическими, чтобы они могли иметь доступ к данным класса. Напомним, что статические ф-ции-эл-ты могут иметь доступ только к статическим данным-эл-там класса. Унарная операция,(напр. !) , м. б. перегружена как ф-ция с одним аргументом, не являющаяся Эл-том, двумя различными способами: либо с аргументом, к-ый явл-ся объектом (это требует копирования объ­екта, чтобы побочные эффекты ф-ции не оказывали влияния на исходный объект), либо с аргументом, к-ый явл-ся ссылкой на объект (никакой копии исходного объекта при этом не делается, но все побочные эффекты этой ф-ции оказывают влияние на исходный объект). Если s — объект класса String (или ссылка на объект класса String), то !s трактуется как вызов operator!(s), активизирующий дружественную ф-цию, не являющуюся Эл-том класса String, но объявленную в нем следующим образом:

class String {

friend int operator!( const String &);}

Перегрузка бинарных операций

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

Вопрос 16. Перегрузка ++ и --.

Всякая ф-я-член имеет неявный аргумент, соответствующий ключ. слову this и являющийся указателем на объект , членом которого служит данная ф-я. => при перегрузке унарных операторов с помощью ф-и-члена нет необх-ти для этой ф-и иметь какие-либо аргументы. Единственный необх. аргумент – указатель на объект.

Для того, чтобы выполнить перегрузку унарного оператора с помощью friend-функции, необходимо исп-ть параметр ссылочного типа.

Различаются префиксная и постфиксная формы операторов ++ и --.

Если ++el, то выз-ся operator++(), иначе operator++(int x), где х принимает зн-е «0».

Все операции инкремента и декремента в префиксной и постфиксной фор­мах могут быть перегружены.

Чтобы перегрузить операцию инкремента для получения возможности использования и префиксной, и постфиксной форм, каждая из этих двух перегруженных ф-ций-операций должна иметь разную сигнатуру, чтобы компилятор имел возможность определить, какая версия ++ имеется в виду в каждом конкретном случае. Префиксный вариант перегружается точно так же, как любая другая префиксная унарная операция.

++dl

он генерирует вызов функции operator++(dl)

прототип к-ой д. б. объявлен в классе Date как дружественный:

friend Date operator++(Date &);

Перегрузка постфиксной формы операции инкремента представляет не­которые трудности, так как компилятор должен быть способен различать сигнатуры перегруженных ф-ций-операций инкремента в префиксной и постфиксной формах. В этом случае, когда компилятор встречает выражение постфиксной формы инкремента генерирует вызов функции

dl.operator++(0)

прототипом которой является Date operator++(int)

NULL (0) в генерируемом вызове функции является чисто формальным значением, введенным для того, чтобы сделать список аргументов ф-ции operator++, используемой для постфиксной формы инкремента, отличным от списка аргументов ф-ции operator++, используемых для префиксной формы инкремента.

Если постфиксная форма операции инкремента реализуется как ф-ция, не явл-ся Эл-том, то, когда компилятор встречает выражение

dl++

он генерирует вызов функции cperator++(dl,0)

прототип которой должен иметь вид

friend Date operator++(Date &, int);

Опять формальный аргумент NULL используется компилятором только для того, чтобы список аргументов ф-ции operator++, к-ая используется для постфиксной формы инкремента, отличался от списка аргументов ф-ции operator++, используемой для префиксной формы инкремента.

Все рассмотренное в этом разделе по отношению к перегрузке операций инкремента в префиксной и постфиксной формах, приложено и к перегрузке операций декремента.