|
Программирование >> Структурное программирование
и проверки на равенство реализуется с использованием функции strcmp из стандартной библиотеки С. Многие программисты на С++ отстаивают использование одних перегруженных функций-операций для реализации других функций. Например, перегруженная функция операция opera tor >= могла бы быть реализована следующим образом: int String::operator>=(const String Sright) const { return (*this > right *this == right) ? 1 : 0;} Такое определение функции-элемента operator>= использует перегруженные операции > и == , чтобы определить, больше ли один объект типа String другого объекта того же типа или не равны ли они. Реализация функций-элементов, использующих определенные ранее функции-элементы, позволяет программисту уменьшить размер кода, который должен быть написан в начале класса, и увеличить объем повторно используемого кода в классе. Строка char soperator[](int); возвращение ссьшки на символ объявляет перегруженную операцию индексации. Когда компилятор встречает выражение вида stringl[0], он генерирует вызов функции stringl.operator[](0). Функция operator[] сначала использует assert, чтобы выполнить проверку, находится ли индекс внутри допустимого диапазона; если индекс находится вне диапазона, программа печатает сообщение об ошибке и аварийно завершается. Если индекс внутри диапазона, operator[] возвращает соответствующий символ строки объекта класса String как char &; эту ссылку char & можно использовать как L-величину для модификации указанного символа строки объекта класса String. Строка string operator О (int, int); возвращение подстроки объявляет перегруженную операцию вызова функции. В классах строк принято перегружать эту операцию для выделения подстроки из объекта класса String. Два целых параметра указывают индекс начала и длину подстроки, выделяемой в строке объекта класса String. Если индекс начала находится вне допустимого диапазона или длина подстроки отрицательная, выдается сообщение об ошибке. По соглашению, если длина подстроки равна О, то подстрока выделяется во всех случаях до конца строки в объекте класса String. Например, предположим, что stringl является объектом класса String, содержащим строку символов AEIOU . Когда компилятор встречает выражение stringl(2,2), он генерирует вызов функции stringl.operator()(2,2). При выполнении этого вызова создается временный объект String, содержащий строку Ю , и возвращается копия этого объекта. Перегрузка операций вызова функций () является мощным средством, потому что функции могут получать списки параметров произвольной длины и сложности. Мы можем использовать эти возможности для многих интересных задач. Одним из таких применений операции вызова функции является альтернативная запись индексированного массива: вместо неудобной принятой в С записи двойных квадратных скобок для двумерного массива, имеющей вид а[Ь][с], некоторые программисты предпочитают перегрузить операцию вызова функции, чтобы иметь возможность записывать а(Ь, с). Перегруженная операция вызова функции может быть только нестатической функцией-элементом. Эта операция используется только когда имя функции является объектом класса String. 8.11. Перегрузка ++ и ~ Все операции инкремента и декремента в префиксной и постфиксной формах могут быть перегружены. Мы увидим, как компилятор различает префиксные или постфиксные варианты операций инкремента или декремента. Чтобы перегрузить операцию инкремента для получения возможности использования и префиксной, и постфиксной форм, каждая из этих двух перегруженных функций-операций должна иметь разную сигнатуру, чтобы компилятор имел возможность определить, какая версия ++ имеется в виду в каждом конкретном случае. Префиксный вариант перегружается точно так же, как любая другая префиксная унарная операция. Предположим, например, что мы хотим прибавить 1 к дню в объекте dl класса Date. Когда компилятор встречает выражение с префиксным инкрементом ++dl компилятор генерирует вызов функции-элемента dl.operator++() прототип которой должен иметь вид Date operator++(); Если префиксная форма инкремента реализуется как функция, не являющаяся элементом, то, когда компилятор встречает выражение ++dl он генерирует вызов функции operator++(dl) прототип которой должен быть объявлен в классе Date как дружественный: friend Date operator++(Date &); Перегрузка постфиксной формы операции инкремента представляет некоторые трудности, так как компилятор должен быть способен различать сигнатуры перегруженных функций-операций инкремента в префиксной и постфиксной формах. По соглашению, принятому в С++, когда компилятор встречает выражение постфиксной формы инкремента Строка int getLengthO const; возвращение длины строки объявляет функцию, которая возвращает длину объекта String. Заметим, что эта функция нолучает длину путем возвращения значения закрытых данных класса String. Теперь читатель может сам просмотреть программу main, изучить выходные данные программы и исследовать результаты каждого использования перегруженной операции. 8.12. Учебный пример: класс дата Рисунок 8.6 иллюстрирует класс Date. Класс использует перегруженные операции инкремента в префиксной и постфиксной формах для прибавления 1 к дню в объекте Date, что может вызвать в ряде случаев увеличение на 1 и месяца и года. Класс имеет следующие функции-элементы: перегруженную операцию поместить в поток, конструктор с умолчанием, функцию setDate, перегруженные функции-операции инкремента в префиксной и постфиксной формах, перегруженную операцию сложения с присваиваем (+=), функцию проверки високосного года и функцию, определяющую, является ли указанный день последним днем месяца. Программа драйвера в main создает объекты дат: dl, которая по умолчанию получает начальное значение Январь 1, 1900, d2, которая получает начальное значение Декабрь 27, 1992 и d3, которой программа пытается присвоить неправильную дату. Конструктор класса Date вызывает setDate для установки заданных значений месяца, дня и года. Если месяц неправильный, он устанавливается равным 1. Неправильный год устанавливается равным 1900. Неправильный день устанавливается равным 1. он генерирует вызов функции dl.operator++(0) прототипом которой является Date operator++(int) Нуль (0) в генерируемом вызове функции является чисто формальным значением, введенным для того, чтобы сделать список аргументов функции operator++, используемой для постфиксной формы инкремента, отличным от списка аргументов функции operator++, используемых для префиксной формы инкремента. Если постфиксная форма операции инкремента реализуется как функция, не являющаяся элементом, то, когда компилятор встречает выражение dl++ он генерирует вызов функции operator++(dl,0) прототип которой должен иметь вид friend Date operator++(Date &, int); Опять формальный аргумент О используется компилятором только для того, чтобы список аргументов функции operator++, которая используется для постфиксной формы инкремента, отличался от списка аргументов функции operator-f-f-, используемой для префиксной формы инкремента. Все рассмотренное в этом разделе по отношению к перегрузке операций инкремента в префиксной и постфиксной формах, приложимо и к перегрузке операций декремента.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |