Вывод

<!--StartFragment -->

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

Вывод Встроенных Типов

Класс ostream определяется вместе с операцией << (\"поместить в\") для обработки вывода встроенных типов:


class ostream {
// ...
public:
ostream& operator<<(char*);
ostream& operator<<(int i) { return *this<



Некоторые Подробности Разработки

Операция вывода используется, чтобы избежать той многословности, которую дало бы использование функции вывода. Но почему < Возможности изобрести новый лексический символ нет. Операция присваивания была кандидатом одновременно и на ввод, и на вывод, но оказывается, большинство людей предпочитают, чтобы операция ввода отличалась от операции вывода. Кроме того, = не в ту сторону связывается (ассоциируется), то есть cout=a=b означает cout=(a=b).

Делались попытки использовать операции < и >, но значения \"меньше\" и \"больше\" настолько прочно вросли в сознание людей, что новые операции ввода/вывода во всех реальных случаях оказались нечитаемыми. Помимо этого, \"<\" находится на большинстве клавиатур как раз на \",\", и у людей получаются операторы вроде такого:

cout < x , y , z;

Для таких операторов непросто выдать хорошие сообщения об ошибках.

Операции << и >> к такого рода проблемам не приводят, они асимметричны в том смысле, что их можно проассоциировать с \"в\" и \"из\", а приоритет << достаточно низок, чтобы можно было не использовать скобки для арифметических выражений в роли операндов.

Например:

cout << \"a*b+c=\" << a*b+c << \"\\n\";

Естественно, при написании выражений, которые содержат операции с более низкими приоритетами, скобки использовать надо.

Например:

cout << \"a^b|c=\" << (a^b|c) << \"\\n\";

Операцию левого сдвига тоже можно применять в операторе вывода:

cout << \"a<

Форматированный Вывод

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

char* oct(long, int =0); // восьмеричное представление
char* dec(long, int =0); // десятичное представление
char* hex(long, int =0); // шестнадцатиричное представление
char* chr(int, int =0); // символ
char* str(char*, int =0); // строка

Если не задано поле нулевой длины, то будет производиться усечение или дополнение; иначе будет использоваться столько символов (ровно), сколько нужно.

Например:
 

 


cout << "dec(" << x
<< ") = oct(" << oct(x,6)
<< ") = hex(" << hex(x,4)
<< ")";
 

 


Если x==15, то в результате получится:

dec(15) = oct( 17) = hex( f);

Можно также использовать строку в общем формате:

char* form(char* format ...);
cout<
 



Виртуальная Функция Вывода

Иногда функция вывода должна быть virtual. Рассмотрим пример класса shape, который дает понятие фигуры:
 

 


class shape {
// ...
public:
// ...
virtual void draw(ostream& s); // рисует "this" на "s"
};


class circle : public shape {
int radius;
public:
// ...
void draw(ostream&);
};
 

 


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

Чтобы поддерживать для таких классов стандартную парадигму вывода, операция << определяется так:
 

 


ostream& operator<<(ostream& s, shape* p)
{
p->draw(s);
return s;
}
 

 


Если next - итератор типа определенного в #7.3.3, то список фигур распечатывается например так:

while ( p = next() ) cout << p;

 



Опубликовал admin
23 Мар, Вторник 2004г.



Программирование для чайников.