Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции C++.doc
Скачиваний:
7
Добавлен:
01.05.2025
Размер:
1.44 Mб
Скачать

8.9 Собственные операторы извлечения и вставки

Поскольку основанные на массивах потоки продолжают оста­ваться потоками, то можно создавать собственные функции извлечения и вставки в точности тем же способом, что и для потоков других типов. Например, в следующей программе создается класс plot, поддерживающий координаты X и Y точек в двумерном пространстве. Перегруженный для этого клас­са оператор вставки отображает положение точки. Для простоты область изменения координат X и Y ограничена пределами от 0 до 5.

#include <strstrea.h>

#include <iostream.h>

const int size=5;

class plot

{

int x, y;

public:

plot(int i, int j)

{

if(i>size) i = size;

if(i<0) i=0;

if(j>size) j = size;

if(j<0) j=0;

x=i; y=j;

}

friend ostream& operator<<(ostream &stream, plot p);

}

ostream& operator<<(ostream &stream, plot p)

{

stream << p.x << “ “ << p.y << “\n”;

return stream;

}

int main()

{

plot a(2, 3), b(1, 1);

cout << "Output using cout:\n";

cout << a << “\n” << b << "\n\n";

char str[200];

ostrstream outs(str, sizeof(str));

outs << а << b << ends;

cout << "Output using in-RAM formatting:\n";

cout << str;

}

Эта программа выведет следующий результат:

Output using cout:

2 3

1 1

Output using in-RAM formatting:

2 3

1 1

8.10 Форматирование на основе массивов

В языке С функции sprintf() и sscanf() особенно полезны для подготовки данных к выводу или чтения входных данных с нестандартных устройств. Тем не менее, благодаря возможности языка C++, перегружая операторы вставки и извлечения для соответствующего класса и создавая соб­ственные манипуляторы, можно достаточно легко работать со многими экзотическими устрой­ствами. Благодаря сказанному, потребность в форматировании в памяти не так уж и велика. Тем не менее, остается много приложений для такого форматирования.

Одним из распространенных применений форматирования на основе массивов служит конст­руирование строки, используемой в качестве входа или функции стандартной библиотеки, или какой-то другой внешней функции. Например, может потребоваться создать строку, которая будет передана функции strtok() для синтаксического разбора. Функция strtok() разбивает стро­ку на ее элементы. Другим применением ввода/вывода на основе массивов служат текстовые ре­дакторы, выполняющие сложные операции форматирования. Часто проще использовать конст­рукции форматированного ввода/вывода C++ на основе массивов для построения сложной строки, чем использовать для этого «подручные» средства.

Глава 9. Шаблоны и библиотека stl

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

9.1 Функции-шаблоны

Функция-шаблон определяет общий набор операций, который будет применен к данным различ­ных типов. Используя этот механизм, можно применять некоторые общие алгоритмы к широко­му кругу данных. Как известно, многие алгоритмы логически одинаковы вне зависимости от типа данных, с которыми они оперируют. Например, алгоритм быстрой сортировки quicksort один и тот же и для массива целых чисел, и для массива чисел с плавающей запятой. Отличается только тип данных, подлежащих сортировке. При помощи создания функции-шаблона (generic function) можно определить сущность алгоритма безотносительно к типу данных. После этого компилятор автоматически генерирует корректный код для того типа данных, для которого создается данная конкретная реализация функции на этапе компиляции. По существу, когда создается функция-шаблон, создается функция, которая может автоматически перегружать сама себя.

Функции-шаблоны создаются с использованием ключевого слова template (шаблон). Обычное значение слова «шаблон» достаточно полно отражает его использование в C++. Шаблон исполь­зуется для создания каркаса функции, оставляя компилятору реализацию подробностей. Общая форма функции-шаблона имеет следующий вид:

template<class тип1, class тип2, ...> возвращаемый_тип имя_функции(список параметров)

{

// тело функции

}

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

Ниже приведен короткий пример, в котором создается функция-шаблон, имеющая два пара­метра. Эта функция меняет между собой величины значений этих параметров. Поскольку общий процесс обмена значениями между двумя переменными не зависит от их типа, то он естествен­ным способом может быть реализован с помощью функции-шаблона.

#include <iostream.h>

template <class X> void swap(X &a, X &b)

{

X temp = a; a = b; b = temp;

}

int main()

{

int i=10, j=20;

float x=10.1, y=23.3;

char a='x', b='z';

cout << "Original i, j: " << i << “ “ << j << endl;

cout << "Original x, y: " << x << “ “ << у << endl;

cout << "Original a, b: " << a << “ “ << b << endl;

swap(i, j); // обмен целых

swap(x, y) ; // обмен вещественных значений

swap(a, b) ; // обмен символов

cout << "Swapped i, j: " << i << “ “ << j << endl;

cout << "Swapped x, y: " << x << “ “ << у << endl;

cout << "Swapped a, b: " << a << “ “ << b << endl;

return 0;

}

Рассмотрим эту программу более внимательно. Строка

template <class X> void swap(X &a, X &b)

указывает компилятору, что создается шаблон. Здесь X — имя параметра-типа. Далее следует объявление функции swap() с использованием типа данных X для тех параметров, которые будут обмениваться значениями. В функции main() функция swap() вы­зывается с передачей ей данных трех различных типов: целых чисел, чисел с плавающей запятой и символов. Поскольку функция swap() является функцией-шаблоном, то компилятор автоматичес­ки создаст три разные версии функции swap() — одну для работы с целыми числами, другую для работы с числами с плавающей запятой и, наконец, третью для работы с переменными символь­ного типа.