Литмир - Электронная Библиотека
A
A

Среди наших любимых типов, которых нет в библиотеке, — классы

Matrix
(см. главу 24),
Date
(см. главу 9) и целые числа с бесконечной точностью (поищите в веб класс
Bignum
). Если вы еще раз поразмыслите над этим, то поймете, что язык не может поддерживать десятки тысяч типов: кто их определит, кто их реализует, как их найти и какое толстое руководство по использованию языка при этом получится? Как и большинство современных языков программирования, язык С++ решает эту проблему, позволяя программисту при необходимости определять свои собственные типы (типы, определенные пользователем).

6.3.3. Реализация лексем

Как должна выглядеть лексема в нашей программе? Иначе говоря, как должен выглядеть тип

Token
? Класс
Token
должен предусматривать выполнение операторов, например
+
и
, а также представлять числа, такие как
42
и
3.14
. В самой простой реализации нужно придумать, как задать вид лексемы и как хранить числа.

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

Существует много способов реализации этой идеи в программе на языке С++. Вот ее простейший вариант:

class Token { // очень простой тип, определенный пользователем

public:

  char kind;

  double value;

};

Класс

Token
— это тип (такой же, как
int
или
char
), поэтому его можно использовать для определения переменных и хранения значений. Он состоит из двух частей (членов):
kind
и
value
. Ключевое слово
class
означает “тип, определенный пользователем”; это значит, что он содержит члены (хотя в принципе может их и не содержать). Первый член,
kind
, имеет тип
char
и представляет собой символ. С его помощью удобно хранить символы
'+'
и
'*'
, чтобы представить операции
*
и
+
. Рассмотрим пример использования этого типа.

Token t;       // t — объект класса Token

t.kind = '+';  // t представляет операцию +

Token t2;      // t2 — другой объект класса Token

t2.kind = '8'; // цифра 8 означает, что "вид" является числом

t2.value = 3.14;

Для доступа к члену класса используется обозначение имя_объекта.имя_члена. Выражение

t.kind
читается как “член
kind
объекта
t
”, а выражение
t2.value
— как “член
value
объекта
t2
”. Объекты класса
Token
можно копировать так же, как и переменные типа
int
.

Token tt = t;    // копирование при инициализации

if (tt.kind != t.kind) error("невозможно!");

t = t2;          // присваивание

cout << t.value; // вывод числа 3.14

Имея класс

Token
, можно выразить выражение
(1.5+4)*11
с помощью семи лексем.

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

Обратите внимание на то, что для простых лексем значение не требуется, поэтому мы не используем член

value
. Нам нужен символ для обозначения чисел. Мы выбрали символ
'8'
просто потому, что он явно не оператор и не знак пунктуации. Использование символа
'8'
для обозначения чисел немного загадочно, но это лишь на первых порах.

Класс

Token
представляет пример типа, определенного пользователем. Тип, определенный пользователем, может иметь функции-члены (операции), а также данные члены. Существует много причин для определения функций-членов. В данном примере мы описали две функции-члена для того, чтобы инициализация объекта класса
Token
стала проще.

class Token {

public:

  char kind;     // вид лексемы

  double value;  // для чисел: значение

  Token(char ch) // создает объект класса Token

                 // из переменной типа char

    :kind(ch), value(0) { }

  Token(char ch, double val)   // создает объект класса Token

    :kind(ch), value(val) { }  // из переменных типа

                               // char и double

};

Эти две функции-члена называют конструкторами (constructors). Их имя совпадает с именем типа, и они используются для инициализации (конструирования) объектов класса

Token
. Рассмотрим пример.

Token t1('+');      // инициализируем t1, так что t1.kind = '+'

Token t2('8',11.5); // инициализируем t2,

                    // так что t2.kind = '8' и t2.value = 11.5

В первом конструкторе фрагмент

:kind(ch)
,
value(0)
означает “инициализировать член kind значением переменной
ch
и установить член
value
равным нулю”. Во втором конструкторе фрагмент
:kind(ch)
,
value(val)
означает “инициализировать член
kind
значением переменной
ch
и установить член
value
равным переменной val”. В обоих вариантах нам требуется лишь создать объект класса
Token
, поэтому тело функции ничего не содержит:
{ }
. Специальный синтаксис инициализации (список инициализации членов класса) начинается с двоеточия и используется только в конструкторах.

78
{"b":"847443","o":1}