|
Программирование >> Структурное программирование
из своих аргументов в виде объекта класса. Этот аргумент должен быть указан явно в списке при вызове функции, не являющейся элементом. При перегрузке операций ( ), [], -> или = функция перегрузки операции должна быть объявлена как элемент класса. Для других операций функции перегрузки операций могут не быть функциями-элементами (тогда они обычно объявляются друзьями). Реализована ли функция-операция как функция-элемент или нет, операция в выражении реализуется одинаково. Так какая же реализация лучше? Когда функция-операция реализована как функция-элемент, крайний левый (или единственный) операнд должен быть объектом того класса (или ссылкой на объект того класса), элементом которого является функция. Если левый операнд должен быть объектом другого класса или встроенного типа, такая функция-операция не может быть реализована как функция-элемент (мы будем это делать в разделе 8.5 при перегрузке и как операций поместить в поток и взять из потока соответственно). Функция-операция, реализованная не как функция-элемент, должна быть другом, если эта функция должна иметь прямой доступ к закрытым или защищенным элементам этого класса. Перегруженная операция должна иметь левый операнд типа ostream & (такой, как cout в выражении cout classObject), так что она не может быть функцией-элементом. Аналогично, перегруженная операция должна иметь левый операнд типа istream & (такой, как cin в выражении cin classObject), так что она тоже не может быть функцией-элементом. К тому же каждая из этих перегруженных функций-операций может потребовать доступа к закрытым элементам данным объекта класса, являющегося входным или выходным потоком, так что эти перегруженные функции-операции делают иногда функциями-друзьями класса из соображений эффективности. Совет по повышению эффективности 8.1 Можно было бы перегружать операцию не как элемент и не как дружественную функцию, но такая функция, нуждающаяся в доступе к закрытым или защищенным данным класса, потребовала бы использования функций set или get, предусмотренных открытым интерфейсом этого класса. Накладные расходы на вызовы этих функций могли бы вызвать ухудшение производительности. Функции-элементы операций вызываются только в случае, если левый операнд бинарной операции или единственный операнд унарной операции являются объектом того класса, элементом которого является функция. Другая причина того, что для перегрузки операции можно выбирать функцию, не являющуюся элементом, состоит в возможности сделать операцию коммутативной. Например, мы имеем объект number типа long int и объект biglntegerl класса Hugelnteger (класса, в котором целые могут быть произвольно большими и не ограниченными размерами машинного слова используемого оборудования; класс Hugelnteger разработан в упражнениях к данной главе). Операция сложения (-I-) создает временный объект Hugelnteger как сумму long int и Hugelnteger (как в выражении number -1-biglntegerl). Таким образом, мы требуем, чтобы операция сложения была коммутативной (как это обычно и есть). Проблема состоит в том, что объект класса должен находиться слева от знака сложения, если операция перегружена как функция-элемент. Поэтому мы перегружаем операцию как друга. 8.5. Перегрузка операций поместить в поток и взять из потока С-Н- способен вводить и выводить стандартные типы данных, используя операцию поместить в поток и операцию взять из потока . Эти операции уже перегружены в библиотеках классов, которыми снабжены компиляторы С-Ь-Ь, чтобы обрабатывать каждый стандартный тип данных, включая строки и адреса памяти. Операции поместить в поток и взять из потока можно также перегрузить для того, чтобы выполнять ввод и вывод типов, определенных пользователем. Программа на рисунке 8.3 демонстрирует перегрузку операций поместить в поток и взять из потока для обработки данных определенного пользователем класса телефонных номеров PhoneNumber. В этой программе предполагается, что телефонные номера вводятся правильно. Проверку ошибок мы оставляем для упражнений. На рис. 8.3 функция-операция взять из потока (operator ) получает как аргументы ссылку input типа istream, и ссылку, названную num, на определенный пользователем тип PhoneNumber; функция возвраш;ает ссылку типа istream. Функция-операция (operator ) используется для ввода номеров телефонов в виде (800) 555-1212 в объекты класса PhoneNumber. Когда компилятор видит выражение cin >> phone В main, он генерирует вызов функции operator>>(cin, phone); После выполнения этого вызова параметр input становится псевдонимом для cin, а параметр num становится псевдонимом для phone. Функция-операция использует функцию-элемент getline класса istream, чтобы прочитать как строки три части телефонного номера вызванного объекта класса PhoneNumber (num в функции-операции и phone в main) в areaCode (код местности), exchange (коммутатор) и line (линия). Функция getline детально объяснена в главе 11. Символы круглых скобок, пробела и дефиса пропускаются при вызове функции-элемента ignore класса istream, которая отбрасывает указанное количество символов во входном потоке (один символ по умолчанию). Функция operator возвращает ссылку input типа istream (т.е. cin). Это позволяет операциям ввода объектов PhoneNumber быть сцепленными с операциями ввода других объектов PhoneNumber или объектов других типов данных. Например, два объекта PhoneNumber могли бы быть введены следующим образом: cin phonel phone2; Сначала было бы выполнено выражение cin phonel путем вызова operator (cin, phonel); чтобы позволить Hugelnteger находиться справа от знака сложения. Функция operator+, которая имеет дело с Hugelnteger, расположенным только слева, может быть и функцией-элементом. PhoneNumber phone; создание объекта phone cout << Введите номер телефона в ; виде (123) 456-7890: endl; cin >> phone активизирует функцию operator>> путем вызова operator>> (cin, phone), cin >> phone; cout << phone активизирует функцию operator<< путем вызова operator<< (cout, phone). cout << Был введен номер телефона: <<endl phone << endl; return 0; } Рис. 8.3. Определенные пользователем операции поместить в поток и взять из потока (часть 1 из 2) FIG8 3.CPP Перегрузка операций поместить в поток и взять из потока. #include <iostream.h> class PhoneNumber{ friend ostream &operator << (ostream &, const PhoneNumber &); friend istream Soperator >> (istream &, PhoneNumber &); private: char areaCode[4]; трехцифровой код местности и нулевой символ char exchange[4]; трехцифровой коммутатор и нулевой символ char line[5]; четырехцифровая линия и нулевой символ Перегруженная операция поместить в поток (она не может быть функцией элементом). ostream &operator (ostream soutput, const PhoneNumber &num) { output ( num.areaCode ) <<num. exchange << - num. line; return output; разрешает cout << a << b <<c; Перегруженная операция взять из потока istream &operator>> (istream sinput, PhoneNumber &num) { input.ignore 0; пропуск ( input.getline(num.areaCode, 4); ввод кода местности input.ignore (2); пропуск ) и пробела input.getline(num.exchange, 4); ввод коммутатора input.ignore О; пропуск дефиса (-) input.getline(num.line, 5); ввод линии return input; разрешает cin >> a >>b >>c; main()
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |