Создание потоковых объектов
Простейший способ сделать класс потоковым состоит в использовании макрокоманд, предусмотренных в библиотеке постоянных потоков. Для большинства классов будут работать следующие шаги.
(прямо или косвенно).
DECLARE_STREAMABLE.
IMPLEMENT_STREAMABLE. Рекомендуется также добавление макрокоманды IMPLEMENT_CASTABLE.
функций-элементов Read и Write.
Чтобы определить потоковый класс, вам нужно:
DECLARE_STREAMABLE, например:
#include <objstrm.h>
class Sample : public TStreamableBase
{
public:
// функции-элементы и т.д.
private:
int i;
DECLARE_STREAMABLE(IMPEXPMACRO, Sample, 1);
};
Классы, шаблоны и макрокоманды, необходимые для определения
потокового класса, предусмотрены в файле objstrm.h. Каждый потоковый класс должен наследовать (прямо или косвенно) из класса
TStreamableBase. В данном примере класс Sample наследует непосредственно из TStreamable. Класс, производный из Sample, не будет
явно наследовать из TStreamableBase, поскольку это уже делает
Sample. Если вы используете множественное наследование, то следует сделать TStreamableBase виртуальной базой. Это несколько увеличит классы, но никакого отрицательного эффекта не окажет.
В большинстве случае для определения потокового класса достаточно макрокоманды DECLARE_STREAMABLE. Эта макрокоманда воспринимает три параметра. Первый из них используется при компиляции
DLL. Второй параметр - это имя определяемого класса, а третий номер версии для этого класса. Потоковый код не обращает внимание
на номер версии класса.
DECLARE_STREAMABLE добавляет в ваш класс конструктор, воспринимающий параметр типа Streamable. Он предназначен для применения в потоковом коде, и непосредственно не используется.
DECLARE_STREAMABLE создает также для вашего класса два экстрактора, так что вы можете записывать объекты для считывания их из
постоянных потоков. Для класса приведенного выше примера класса
Sample эти функции имеют следующие прототипы:
opstream& operator << { opstream&, const Sample& };
opstream& operator << { opstream&, const Sample* };
opstream& operator >> { opstream&, Sample& };
opstream& operator >> { opstream&, Sample*& };
Первый инсертер записывает объекты типа Sample. Второй записывает объекты, указываемые указателем на Sample. Это позволяет
вам использовать полиморфизм и полностью управлять потоками, то
есть полностью записывать объекты типов, производных от Sample.
Затем эти объекты считываются обратно с помощью экстрактора, который будет считывать их фактический тип. (Экстрактор выполняет
действие, обратное инсертеру.)
Наконец, DECLARE_STREAMABLE создает на базе класса TStreamer
вложенный класс с именем Streamer, который определяет ядро потокового кода.