Unsigned char character; // Символ

Int foreground; // Цвет символа

Int background; // Цвет фона

Bool blink; // Мигание включено/выключено

};

Void main()

{

Cell screen[25][80];

...

}

Перегрузка операторов

В 3-й лекции (п. 4) были описаны средства перегрузки функций. Си++ допус-

кает перегрузку не только функций, но и операторов, таких, как _______"+", "-", "*" (и боль-

шинство других – "+=", "->" и даже "()"). Средства перегрузки операторов полезны

Тогда, когда желательно, чтобы пользовательские типы данных в исходном тексте

программ выглядели в выражениях подобно встроенным типам Си++. Поясним это на

Нескольких примерах.

Для сложения комплексных чисел (описание структуры см. п.2) можно приме-

нить функцию:

Complex C_add(const Complex& x, const Complex& y)

{

Complex t;

t.re = x.re + y.re;

t.im = x.im + y.im;

return t;

}

Параметры функции "C_add(...)" передаются по ссылке, и, кроме того, опи-

Саны как константы, чтобы запретить изменения параметров внутри функции. Пере-

Дача по ссылке обеспечивает эффективный вызов функции, без копирования парамет-

Ров, а константное описание защищает параметры от изменений.

106

Допустим, в программе реализована также функция "C_mult(...)" для умно-

Жения двух комплексных чисел. Ниже приведен пример использования этих функ-

ций:

Complex u, v, w, z, t;

...

t = C_add(u, v);

w = C_mult(z, t);

Конечно, более естественной является запись:

Complex u, v, w, z;

...

w = z * (u + v);

Тип "Complex" является типом, введенным пользователем, и, естественно, в

языке Си++ арифметические операторы для этого типа не определены. Поэтому для

естественной записи выражений с числами в виде структур "Complex" надо перегру-

зить операторы сложения и умножения:

Complex operator +(const Complex& x, const Complex& y)

{

Complex t;

t.re = x.re + y.re;

t.im = x.im + y.im;

return t;

}

Complex operator *(const Complex& x, const Complex& y)

{

Complex t;

t.re = x.re*y.re - x.im*y.im;

t.im = x.re*y.im + x.im*y.re;

return t;

}

Правила размещения перегруженных операторов в исходном тексте программ

Аналогичны правилам размещения функций: прототипы отдельно, определения от-

Дельно (возможно, прототипы операторов расположены в заголовочном файле, а оп-

Ределения – в файле реализации).

Аналогично арифметическим операторам, в Си++ допускается перегружать

операторы потокового ввода/вывода ">>" и "<<". Например, вывести комплексное

число на экран можно так:

Void main()

{

Complex u, v;

u.re = 2.1; u.im = 3.6;

v.re = 6.5; v.im = 7.8;

cout << "Числа равны (" << u.re << " + " << u.im << "i) и ";

cout << " (" << v.re << " + " << v.im << "i).\n";

}

107

В результате выполнения этой программы на экране будет напечатана строка:

Числа равны (2.1 + 3.6i) и (6.5 + 7.8i).

Для упрощения записи операции печати комплексного числа на экране можно

перегрузить оператор вывода в поток:

ostream& operator <<(ostream& s, const Complex& x)

{

s << "(" << x.re << " + " << x.im << "i)";

return s;

}

Void main()

{

Complex u, v;

u.re = 2.1; u.im = 3.6;

v.re = 6.5; v.im = 7.8;

cout << "Числа равны " << u << " и " << v << ".\n";

}

В определении оператора фигурирует тип "ostream". Это класс "поток выво-

да", объектом которого является стандартный поток вывода на экран "cout". Для по-

Токового ввода/вывода в файл необходимо перегружать операторы применительно к

классам "ofstream" и "ifstream" (см. 4-ю лекцию).

Применение структур для реализации стека

Абстрактный тип данных "стек" кратко рассматривался в 8-й лекции (компиля-

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

Компиляторах, но и во многих численных алгоритмах. В данном параграфе рассмат-

риваются два варианта реализации стека на Си++ с помощью структур.

Среди значений английского слова "stack" есть значения "пачка" и "стопа". Аб-

страктный тип данных, соответствующий принципу "последним прибыл – первым

обслужен" получил свое название из-за своего сходства со стопкой тарелок (рис. 1).

Рис. 1..Поведение стека при записи и чтении элементов.

Основные свойства стека:

Элементы добавляются или удаляются только сверху стека.

2) Для добавления элемента применяется функция "push()".

3) Для удаления элемента применяется функция "pop()".

108

Реализация стека на основе статического массива

В качестве задачи поставим разработку стека для хранения вещественных чи-

Сел. Свойства стека очень просты, поэтому для работы со стеком, например, из 20-ти

Вещественных чисел достаточно несложно написать программу, похожую на про-

Грамму 6.1.

#include <iostream.h>

struct Stack {

double v[20];

int top;

};

void push(Stack& s, double val)

{

s.v[s.top] = val;

s.top++;

}

double pop(Stack& s)

{

return s.v[--(s.top)];

}

void init(Stack& s)

{

s.top = 0;

}

bool full(Stack& s)

{

return s.top >= 20;

}

Void main()

{

Stack s;

Init(s); // Инициализация стека

Push(s, 2.31); // Помещение в стек первого элемента

Push(s, 1.19); // Помещение в стек второго элемента

cout << pop(s) << '\n'; // Извлечение верхнего элемента

// и вывод его на экран

Push(s, 6.7); // Помещение в стек элемента

push(s, pop(s)+pop(s)); // Замена двух верхних элементов

// стека их суммой

}

Программа 6.1.

В программе 6.1 стек реализован на базе статического массива, один из элемен-

Тов которого играет роль верхушки стека. Индекс этого элемента хранится в компо-

Ненте top. (рис. 2).

109

Рис. 2..Стек на основе массива с фиксацией верхушки стека. Серым цветом

Обозначены помещенные в стек элементы.

Недостатки структуры данных Stack

Приведенному в п. 6.1 простейшему варианту реализации стека (в виде струк-

туры "Stack") присущи ряд недостатков, которые можно разбить на две группы:

1) Малая гибкость применения

• У стека ограниченный размер (20 элементов).

• В стеке могут храниться только значения типа double.

• Имена функций наподобие "full()" и "init()" очень распростра-

Нены и может возникнуть конфликт этих имен с именами функций из

Других библиотек.

2) Безопасность использования стека

• Внутренние переменные стека не защищены от изменений извне. По-

Этому стек легко повредить путем изменения значений компонент


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: