Читаем Программирование. Принципы и практика использования C++ Исправленное издание полностью

Приступим к разработке типа Token_stream. Что пользователь ждет от него? Очевидно, что нам нужны функции get и putback — именно поэтому мы ввели понятие потока лексем. Класс Token_stream должен создавать объекты класса Token из символов, считанных из потока ввода, поэтому нам необходима возможность создавать объекты класса Token_stream, способные считывать данные из потока cin. Таким образом, простейший вариант класса Token_stream выглядит примерно так:

class Token_stream {

public:

  Token_stream;        // создает объект класса Token_stream,

                         // считывающий данные из потока cin

  Token get;           // получает объект класса Token

  void putback(Token t); // возвращает объект класса Token

                         // обратно

private:

                         // детали реализации

};

Это все, что требуется от пользователя для использования объектов класса Token_stream. Опытные программисты могут поинтересоваться, почему поток cin является единственным возможным источником символов, — просто мы решили вводить символы с клавиатуры. Это решение можно пересмотреть в упражнении, приведенном в главе 7.

Почему мы использовали “длинное” имя putback, а не логичное имя put? Тем самым мы подчеркнули асимметрию между функциями get и putback: мы возвращаем лексему в поток ввода, а не вставляем ее в поток вывода. Кроме того, функция putback есть в классе istream: непротиворечивость имен — полезное свойство. Это позволяет людям запоминать имена функций и избегать ошибок.

Теперь можем создать класс Token_stream и использовать его.

Token_stream ts;    // объект класса Token_stream с именем ts

Token t = ts.get; // получаем следующий объект класса Token из объекта ts

// ...

ts.putback(t); // возвращает объект t класса Token обратно в объект ts

Это все, что нам нужно, чтобы закончить разработку калькулятора.

<p id="AutBody_Root111"><strong>6.8.1. Реализация класса Token_stream</strong></p>

Теперь необходимо реализовать три функции класса Token_stream. Как представить класс Token_stream? Иначе говоря, какие данные необходимо хранить в объекте класса Token_stream, чтобы он мог выполнить свое задание? Необходима память для лексемы, которая будет возвращена обратно в объект класса Token_stream. Для простоты будем считать, что лексемы возвращаются в поток по одной. Этого вполне достаточно для нашей программы (а также для очень многих аналогичных программ). Таким образом, нужна память для одного объекта класса Token и индикатор ее занятости.

class Token_stream {

public:

  Token_stream; // создает объект класса Token_stream,

                  // считывающий данные из потока cin

  Token get;    // получает объект класса Token

                  // (функция get определена в разделе 6.8.2)

  void putback(Token t); // возвращает объект класса Token

                         // обратно

private:

  bool full;    // находится ли в буфере объект класса Token?

  Token buffer; // здесь хранится объект класса Token,

                // возвращаемый в поток функцией putback

};

Теперь можно определить (написать) три функции-члена. Конструктор и функция putback никаких трудностей не вызывают, поскольку они невелики. Мы определим их в первую очередь. Конструктор просто устанавливает настройки, свидетельствующие о том, что буфер пуст.

Token_stream::Token_stream

  :full(false), buffer(0) // в буфере нет ни одного объекта

                          // класса Token

{

}

Определяя функцию-член вне определения самого класса, мы должны указать, какому классу она принадлежит. Для этого используется обозначение имя_класса::имя_функции_члена. В данном случае нам необходимо определить конструктор класса Token_stream. Конструктор — это член класса, имя которого совпадает с именем класса.

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже