Читаем C++ полностью

Описания после метки public: задают интерфейс: пользователь может обращаться только к трем функциям put(). Описания перед меткой public задают представление объекта класса ostream. Имена buf и state могут использоваться только функциями put(), описанными в открытой части.

class определяет тип, а не объект данных, поэтому чтобы использовать ostream, мы должны один такой объект описать (так же, как мы описываем переменные типа int):

ostream my_out;

Считая, что my_out был соответствующим образом проинициализирован (как, объясняется в #1.10), его можно использовать например так:

my_out.put(«Hello, world\n»);

С помощью операции точка выбирается член класса для данного объекта этого класса. Здесь для объекта my_out вызывается член функция put().

Функция может определяться так:

void ostream::put(char* p) (* while (*p) buf.sputc(*p++); *)

где sputc() – функция, которая помещает символ в streambuf. Префикс ostream необходим, чтобы отличить put() ostream'а от других функций с именем put().

Для обращения к функции члену должен быть указан объект класса. В функции члене можно ссылаться на этот объект неявно, как это делалось выше в ostream::put(): в каждом вызове buf относится к члену buf объекта, для которого функция вызвана. Можно также ссылаться на этот объект явно посредством указателя с именем this. В функции члене класса X this неявно описан как X* (указатель на X) и инициализирован указателем на тот объект, для которого эта функция вызвана. Определение ostream::put() можно также записать в виде:

void ostream::put(char* p) (* while (*p) this-»buf.sputc(*p++); *) Операция -» применяется для выбора члена объекта, заданного указателем.

<p>1.8 Перегрузка операций</p>

Настоящий класс ostream определяет операцию ««, чтобы сделать удобным вывод нескольких объектов одним оператором. Давайте посмотрим, как это сделано.

Чтобы определить @, где @ – некоторая операция языка С++, для каждого определяемого пользователем типа вы определяете функцию с именем operator@, которая получает параметры соответствующего типа. Например:

class ostream (* //... ostream operator««(char*); *);

ostream ostream::operator««(char* p) (* while (*p) buf.sputc(*p++); return *this; *)

определяет операцию «« как член класса ostream, поэтому s««p интерпретируется как s.operator««(p), когда s является ostream и p – указатель на символ. Операция «« бинарна, а функция operator««(char*) на первый взгляд имеет только один параметр. Однако, помимо этого она имеет свой стандартный параметр this.

То, что в качестве возвращаемого значения возвращается ostream, позволяет применять «« к результату операции вывода. Например, s««p««q интерпретируется как (s.operator««(p)).operator««(q). Так задаются операции вывода для встроенных типов.

С помощью множества операций, заданных как открытые члены класса ostream, вы можете теперь определить «« для такого определяемого типа, как complex, не изменяя описание класса ostream:

ostream operator««(ostream s, complex z) // у complex две части: действительная real и мнимая imag // печатает complex как (real,imag) (* return s «« "(" «« z.real «« "," «« z.imag «« ")'; *)

Поскольку operator««(ostream,complex) не является функцией членом, для бинарности необходимо два явных параметра. Вывод значений будет производиться в правильном порядке, потому что ««, как и большинство операций С++, группирует слева направо, то есть f««b««c означает (a««b)««c. При интерпретации операций компилятору известна разница между функциями членами и функциями не членами. Например, если z – комплексная переменная, то s««z будет расширяться с помощью вызова стандартной функции (не члена) operator««(s,z).

<p>1.9 Ссылки</p>

К сожалению, последняя версия ostream содержит серьезную ошибку и к тому же очень неэффективна. Сложность состоит в том, что ostream копируется дважды при каждом использовании ««: один раз как параметр и один раз как возвращаемое значение. Это оставляет state неизмененным после каждого вызова. Необходима возможность передачи указателя на ostream вместо передачи самого ostream.

Это можно сделать с помощью ссылок. Ссылка действует как имя для объекта. T amp; означает ссылку на T. Ссылка должна быть инициализирована, и она становится другим именем того объекта, которым она инициализирована. Например:

ostream amp; s1 = my_out; ostream amp; s2 = cout;

Теперь можно использовать ссылку s1 и my_out одинаково, и они будут иметь одинаковые значения. Например, присваивание

s1 = s2;

копирует объект, на который ссылается s2 (то есть, cout), в объект, на который ссылается s1 (то есть, my_out). Члены берутся с помощью операции точка

s1.put(«не надо использовать -»»);

а если применить операцию взятия адреса, то вы получите адрес объекта, на который ссылается ссылка:

amp;s1 == amp;my_out

Первая очевидная польза от ссылок состоит в том, чтобы обеспечить передачу адреса объекта, а не самого объекта, в функцию вывода (в некоторых языках это называется вызов по ссылке):

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных

Все жанры