Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
шпоры по ООП.doc
Скачиваний:
31
Добавлен:
25.09.2019
Размер:
1.04 Mб
Скачать

60.Дружественные шаблоны.

Обычно при объявлении дружественной конструкции, которая является экземпляром шаблона функции или класса, можно точно указать, что именно должно быть дружественным. Иногда, однако, желательно, чтобы дружественными по отношению к классу были все экземпляры шаблона. Отсюда вытекает понятие так называемого дружественного шаблона.

class Manager{

template<typename T>

friend class Task;

template <typename T>

friend void Shedule<T>::dispatch{Task<T>*};

template <typename T>

friend int ticket(){

return ++Manager::counter;}

static int counter;

}

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

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

template <class T>

class matrix {

friend void foo_bar(); // универсальная

friend vect <T> product(vect <T> v); // создается экземпляр };

53.Форматирование в памяти с использованием потоков strstream.

Потоки реализованы отдельно от функций stdio. По этой причине при использовании в программе одновременно и потоков, vTstdio могут возникнуть проблемы. Если один символ выводится потоковой операцией, а другой — функцией stdio putc (...), то порядок появления символов может быть нарушен из-за внутренней буферизации и автоматической сброски буфера.

форматирование в памяти

Очень часто данные нужно форматировать, не отображая их на экране. Для этого в ANSI С используется функция sprintf (...). Форматированные данные сохраняются в буфере памяти для последующей обработки. Библиотека потоков содержит класс форматирования в памяти под названием strstream, который можно использовать и для извлечения, и для вставки. В листинге 7.24 приведен полный пример, который показывает, что с strstream можно работать так же, как и с fstream, используя операторы вставки, манипуляторы и динамическую буферизацию.

Листинг 7.24. Использование strstream для форматирования данных в памяти

#include <iostream.h>

#include <strstrea.h>

#include <iomanip.h>

#include <fstream.h>

#include <stdlib.h>

void main() <

// создание пустого strstream. Память будет выделена

// динамически, по мере необходимости

strstream buffer;

// создаем несколько переменных

int number =30; char* color = "RED"; float weight = 135.96;

// строим в strstream форматированную строку

buffer << "\nThere are " << number;

buffer << "chairs that are " << color;

buffer << ", with a total weight of ";

buffer << setprecision(2) << weight << "kilos.";

// открытие файла

ofstream report("report.doc");

if(!report)

{

cerr << "Can't open the report file.";

exit(l); }

// сохранение данных в файле

report << buffer.rdbuf(); }

В листинге 7.24 показан объект strstream, используемый для построения форматированной строки, которая затем сохраняется в текстовом файле. Файл REPORT.DOC будет содержать следующую строку:

There are 30 chairs that are RED, with a total weight of 135.96 kilos.

Для извлечения данных из форматированной в памяти строки используется класс istrstream.

Вначале нужно создать объект istrstream и ассоциировать его с буфером, содержащим извлекаемые данные. Затем данные извлекаются из потока с помощью обычных операций. Небольшой, но полный пример приведен в листинге 7.25.

Листинг 7.25. Использование istrstream для извлечения данных, форматированных в памяти

#include <iostream.h>

#include <strstrea.h> *

void main(int argc, char** argv) {

istrstream argument(argv[0]);

cout << "\nThere are " << argc

<< " arguments. The first was " << argument.rdbuf(); }

В приведенном примере для инициализации объекта istrstream используется argv[0]. Потоки, как правило, более удобны в обращении, чем простые символьные массивы, так как они гибче, имеют встроенную обработку указателей, динамическое распределение памяти и т.д. Если программы интенсивно работают со строками, то неплохо было бы обдумать переход к strstream или к стандартному классу C++ string, чтобы избавиться от старых ANSI-функций манипулирования строками.