|
Программирование >> Аргументация конструирования
#include <iostream.h> it include <iomanip.h> void cout. < tw ( 8 ) / /ширина поля равна 8... << 10 . . .для 10, но ... 20 для 2 0 равна значению по умолчанию \п ; В результате выполнения этого кода сначала будет выведено восьмисимвольное целое число, а за ним Для вывода двух восьмисимвольных значе- ний нужно сделать так: #include <iostream.h> #include <iomanip.h> void fn,) { cout; < tw (8) установить ширину. . . 10 setw(8) 20 ...обновить ее \n ; Таким образом, если вам нужно вывести несколько значений, но вас не устраивает длина поля по умолчанию, для каждого значения необходимо включать в вывод манипулятор Какой же метод лучше - с использованием манипуляторов иди функций? Ф>нкции-члены предоставляют больше контроля над свойствами потока - хотя бы потому, что их больше. Кроме того, функции-члены обязательно возвращают предыдущее значение изменяемого параметра, так что вы всегда имеете возможность восстановить прежнее значение параметра. И наконец, существуют версии этих функций, позволяющие узнать текущее значение параметра, не изменяя его. Использование этой возможности показано в приведенном ниже примере. finclude <iostream.h> voi loat value) { int previousPrecision; Вы можете узнать текущую точность так: previousPrecision = cout.precision О; жно также сохранить старое значение, одновременно изменяя его на новое previousPrecision = cout.precision(2); cout << value; Восстановим предыдущее значение cout.precision(previousPrecision); Несмотря на все преимущества функционального подхода, манипуляторы более распространены; возможно, просто потому, что они круче выглядят. Используйте то, что вам больше нравится, но в чужом коде будьте готовы увидеть оба варианта. Написаниесоаяеенных C++ обладает потрясающей способностью перегружать оператор сдвига для выполнения вывода. Это значит, что вы тоже можете перегрузить этот оператор, чтобы осуществить вывод собственных классов. Это наиболее важная особенность потоков ввода-вывода, к описанию которой я шел на протяжении всей этой главьс, но до настоящего момента старательно избегал упоминания о ней. Итак, представьте себе, что класс USDollar из главы 24, Перегрузка операторов , дополнен функцией display!). #ifclef WIN32 Iinciude <strstrea.h> #else tinclude otrstream. h> If endl f ttinclude <iomanip.h> class USDollar public: ySDollar(double v = 0.0) Удалим дробную часть dollars = (int)v; Преобразуем дробную часть в центы, добавив 0.5 для округления cents = int((V - dollars) *- 100.0 + 0.5) ; operator return dollars + cents / 100.0; void out) out < << dollars . установим заполнение нулем для центов setfill{0) 3etw(2) cents вернем настройку запол.чения пробелами <<setfill( ) ; protected: unsigned int dollars; unsigned int cents; operator - оператор вставки в поток нашего класса ostreami operator (ostreams о, USDollars d) d.display(о); return o; in (int argcs, char* pArgs [ j ) USDollar usdd .50) ; cour << Начальная сумма = << usd \n ; usd = 2.0 usd; cout Теперь сумка равна usd \n ; return G; Функции play () начинается с вывода символа $, после чего выводится сумма с обязательной десятичной точкой. Обратите внимание, что вывод выполняется в любой потоковый объект ostream, а не только в cout. Это позволяет использовать функцию drsplayO и ддя объектов fstream и strstream, которые являются подклассами класса ostream. Когда приходит время отображать количество центов, функция display () устанавливает ширину поля в два символа и заполнение символом 0. Благодаря этому можно быть уверенным, что числа меньше 10 будут отображены правильно. Обратите внимание, что вместо прямого обращения к функции display!} класс USDollar определяет Теперь программист может выводить объекты класса uSDollar с такой же непринужденностью и изяществом, как и объекты встроенных типов, что и демонстрирует функция main (). В результате выполнения этой программы будут выведены следующие сообщения: НачалБная сумма = $1.50 Теперв сумма равна S3.00 Вы можете поинтересоваться, зачем функция cperator<<() возвращает объект класса ostream, передаваемый ей в качестве аргумента. Дело в том, что это позволяет связывать один оператор с другими операторами в одном и том же выражении. Поскольку operator<< () обрабатывается слева направо, выражение voi о11аг& usd, float i) cout Сумма usd , проценты = i; интерпретируется как void fn.USDollars usd, float i) { (((cou< Сумма ) << usd) << , проценты = ) << i; Первый оператор вставки в поток выводит строку Сумма в cout. Результатом этого выражения является объект cout, который затем передается функции operator<< (ostreams, USDollarS). Поскольку этот оператор возвращает свой объект как ссылку на ostream, данный объект может быть передан следующему в очереди оператору вставки в поток. Если бы типом возвращаемого значения оператора вставки в поток вы объявили void, оператор бы оставался работоспособным, но в приведенном примере вызывал бы ощибку компиляции, поскольку вставить строку в void нельзя. Приведенная же в следующем примере ошибка еще опаснее, поскольку ее трудно обнаружить. ostream operator<<(ostreams os, USDollars usd) ( usd.display(os); return cout;
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |