Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Сериализация, наверное, не знаю как тему назвать правильно 
:(
    Опции темы
Lazin
Дата 18.2.2008, 15:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(Alek86 @  18.2.2008,  15:13 Найти цитируемый пост)
+ боюсь представить, что ЭТО такое. какой у этого класса размер?

этот класс нужен только для того что-бы сработал его конструктор во время запуска программы

Добавлено через 3 минуты и 7 секунд
Цитата(georain @  15.2.2008,  15:18 Найти цитируемый пост)
Потому что во-первых велосипед наверняка, а во вторых надо не забыть каждый класс в таблицу записать и в enum ещё.

эту проблему я и решаю этим классом, можно не в enum записывать, а куда угодно, в простой массив, в объект класса автора  smile 
PM MAIL Skype GTalk   Вверх
Alek86
Дата 18.2.2008, 15:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



Цитата(Lazin @  18.2.2008,  15:24 Найти цитируемый пост)
этот класс нужен только для того что-бы сработал его конструктор во время запуска программы

мой глюк - показалось, что он объект своего типа содержит )


--------------------
user posted image    user posted image
PM MAIL   Вверх
marcusmae
Дата 18.2.2008, 22:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 5
Всего: 39



Цитата(tol05 @  18.2.2008,  15:00 Найти цитируемый пост)
Рефлексия в плюсах есть?

Нет
Цитата(tol05 @  18.2.2008,  15:00 Найти цитируемый пост)
Позднее связывание?

Нет
Цитата(tol05 @  18.2.2008,  15:00 Найти цитируемый пост)
Класс Activator, я имею в виду?

Нет

Если позволите, немного резюмирую всё вышесказанное.

Цитата(Alek86 @  18.2.2008,  15:13 Найти цитируемый пост)
и tol05 и Lazin, фактически, предлагают одно и то же  все равно решение аввтора покрасивше

Код

//CDR - потоковый класс
CDR cdr(input);

//каждый класс содержит функцию create()
class ClassA: public Base{
    public:

    virtual ~ClassA(){};

    static Base * create(CDR * cdr){
        ClassA * bp = new ClassA;
        // тут инициализируем данными, например
        // member = cdr->getMember();
        return bp;
    };    
};

мне не нравится, потому что :
а) статическая функция десериализации
б) создаёт не ClassA *, а Base *. А массив указателей на функции - это всегда кажется, что "финт ушами", особенно если в первый раз делать...

Статичность функции ::create я отношу к недостатком, поскольку она не позволяет "каскадно" или по частям десериализовать объект, опираясь на десериализаторы базовых типов. Топикстартеру придётся в static Base * create(CDR * cdr){ ... } разводить помойку, которая при заявленных аппетитах в сотню классов примет формы опасные для здоровья smile Большинство участников придерживается другой схемы, виртуальной, а именно виртуальный сериализатор + виртуальный десериализатор или виртуальный сериализатор + конструктор-десериализатор.

И тот, и другой способ вполне имеют право на существование. Статический - скорее в случае наличия готовой большой иерархии, к которой сериализацию нужно лишь "временно" прикрутить, чтобы что-то там попробовать. Виртуальный - скорее в случае разработки кОмплексного решения, так, как это обычно делается на современных платформах. В любом случае, странно, что 
Цитата(georain @  18.2.2008,  13:12 Найти цитируемый пост)
ничего лучше чем в первом после я не услышал
, и вообще вдруг выяснилось, что это всё не нужно, и 
Цитата(georain @  18.2.2008,  13:12 Найти цитируемый пост)
как упаковать/распаковать класс, это совсем другая проблема
, а просто 
Цитата(georain @  18.2.2008,  13:12 Найти цитируемый пост)
набор экземпляров этих классов надо максимально эффективно отправлять по сети, причем последовательность типов экземпляров и их количество заранее не известно.
 Я не понимаю, почему georain так уверен в том, что эти две проблемы не связаны. По-моему, задача как раз в том, как упаковать-переправить-распаковать, так чтобы суммарные трудозатраты на это оказались минимальны. Или сокеты нужно применить что ли?!

Цитата(Alek86 @  18.2.2008,  13:46 Найти цитируемый пост)
ты не веришь, что десериализация возможна? )
 Могу привести пример, когда она, как мне кажется, невозможна. Сериализую массив структур "поштучно" и бросаю в перегруженную сеть, которая поперепутала пакеты (или есть сомнения в том, что сеть может менять очерёдность пакетов..?). Предлагаю их десериализовать и расставить ровно в той последовательности, что были изначально.

Это сообщение отредактировал(а) marcusmae - 18.2.2008, 22:26


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
georain
Дата 19.2.2008, 01:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 193
Регистрация: 28.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Lazin, скажи пожалуйста, зачем делать в базовом классе невиртуальные методы-обёртки для виртуальных методов? Чем это лучше, почему не следует сразу виртуальные методы  save_() load_() вызывать?

marcusmae, полность с тобой согласен, единственное только хочу сказать, что естественно внутри static create ,будет вызываться функция - член десериализатор с "каскадной" функциональностью либо поток будет передаваться конструктору, и вот тут
Цитата(marcusmae @  18.2.2008,  22:19 Найти цитируемый пост)
 Могу привести пример, когда она, как мне кажется, невозможна. Сериализую массив структур "поштучно" и бросаю в перегруженную сеть, которая поперепутала пакеты (или есть сомнения в том, что сеть может менять очерёдность пакетов..?). Предлагаю их десериализовать и расставить ровно в той последовательности, что были изначально.

пример очень не удачный, потому как есть протокол TCP гарантирующий доставку в нужном порядке.

PM MAIL   Вверх
georain
Дата 19.2.2008, 02:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 193
Регистрация: 28.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Цитата(marcusmae @  18.2.2008,  22:19 Найти цитируемый пост)
 Я не понимаю, почему georain так уверен в том, что эти две проблемы не связаны. По-моему, задача как раз в том, как упаковать-переправить-распаковать, так чтобы суммарные трудозатраты на это оказались минимальны. Или сокеты нужно применить что ли?!

ИМХО в каждом классе есть метод для превращения класса в кусок потока, и наоборот и есть функция которая по этому куску потока вызывает этот метод для необходимого класса - её функция определить нужный класс. По идее должна быть симметричная  ей функция которая пишет информацию в поток в зависимости от того какой класс записывается, но только потому что класс сам знает свой тип удобнее не делать отдельную функцию, а делать чтобы класс перед тем как "линеаризироваться" записывал информацию о себе сам.
Это две разные задачи и никак не связаны. За вторую задачу может быть ответственен базовый класс, например ISerializable у tol05, первая же задача "каскадно" размазана по методам производных классов. У меня вторая задача тоже размазана по производным классам в статик методах плюс один внешний класс с таблицей которая может быть и внутри базового класса как статический член. Хотя это всё в общем-то довольно удобно, мне кажется что это не очень хорошо. Именно про это и был задан мой вопрос, как лучше (и эффективнее) решить вторую задачу (именно вторую) - нахождение класса из потока, а решение первой задачи довольно тривиальное и тут мало что можно придумать.
Ну вы меня сильно не бейте если чё smile 
PM MAIL   Вверх
marcusmae
Дата 19.2.2008, 02:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 5
Всего: 39



Цитата(georain @  19.2.2008,  02:13 Найти цитируемый пост)
Именно про это и был задан мой вопрос, как лучше (и эффективнее) решить вторую задачу (именно вторую) - нахождение класса из потока, а решение первой задачи довольно тривиальное и тут мало что можно придумать.

Мне кажется, что всё, что можно придумать на счёт сериализации/десериализации основано на той информации, которую предоставляет поток. Не стоит его содержимое считать фиксированным и очевидным. Все идеи - там.

Цитата(georain @  19.2.2008,  01:42 Найти цитируемый пост)
протокол TCP гарантирующий доставку в нужном порядке.

Ахтычорт, TCP, и правда smile Кстати, есть какой-то специфический протокол, построенный для этой задачи над TCP? = Если да, то что он делает?



--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
xvr
Дата 19.2.2008, 08:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(georain @ 19.2.2008,  02:13)
Именно про это и был задан мой вопрос, как лучше (и эффективнее) решить вторую задачу (именно вторую) - нахождение класса из потока, а решение первой задачи довольно тривиальное и тут мало что можно придумать.
Ну вы меня сильно не бейте если чё smile

Чем тебя мое решение не устроило (на 2й странице 3е сверху)?


PM MAIL   Вверх
Lazin
Дата 19.2.2008, 09:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(georain @  19.2.2008,  01:42 Найти цитируемый пост)
скажи пожалуйста, зачем делать в базовом классе невиртуальные методы-обёртки для виртуальных методов? Чем это лучше, почему не следует сразу виртуальные методы  save_() load_() вызывать?

в моем примере оверхеда на вызов дополнительной ф-ии не будет, компилятор ее просто выкинет. 
А преимуществ масса, почитай про паттерн NVI ^_^
PM MAIL Skype GTalk   Вверх
tol05
Дата 19.2.2008, 12:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 1
Всего: 170



Цитата(georain @  19.2.2008,  01:13 Найти цитируемый пост)
За вторую задачу может быть ответственен базовый класс, например ISerializable у tol05, первая же задача "каскадно" размазана по методам производных классов

не ну я так не играю!..  smile  smile  smile 

Что значит размазана? Это расширение функциональности в базовом классе и ее поддержка в производных... Зачем же тогда наследование придумано???
Всвязи с тем, что позднего связывания (в том виде, к которому я уже привык) здесь не имеется, я на своем методе обнаружения классов в потоке не настаиваю... Размазанность - это благо. Каждый класс сам обеспечивает свое жизнеобеспечение.

А по поводу статических ф-ций - это ИМХО плохо. Какое преимущество их использования? Из статической ф-ции производного класса нельзя вызвать статическую ф-цию базового класса, как же тогда инициализировать закрытые члены базового класса? В производном классе к ним доступа нет, а в потоке данные о них есть smile Передавать указатель на текущий объект производного класса в метод его же базового класса? ... Извините ...
Код

class A
{
    public static void F()
    {
    }
}

class B: A
{
    public static void F()//уже здесь у меня warning-и выскакивают. Мы скрываем функциональность базового класса
    {
        //base.F(); нельзя
        A.F();//this в него передавать?! Гм.. прикольно...
    }
}

В статические ф-ции нужно передавать дополнительные параметры, идентифицирующие конкретный объект. Зачем?
Раздувается таблица методов класса. Дублируется значительная часть функциональности....

И как статические ф-ции обеспечивают потокозащищенность в плюсах? Я не помню просто smile

Это сообщение отредактировал(а) tol05 - 19.2.2008, 12:21


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
marcusmae
Дата 19.2.2008, 13:16 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 5
Всего: 39



georain
tol05

Я тут ночью думал-думал и вот что надумал. Что вообще хорошего в статических функциях (при том, что они ужасно плохие  smile)? = А то, что у них адреса фиксированные, и их адын штука на всю генерацию экземпляров класса. А раз так, то пользоваться адресом таких функций просто и удобно (чем georain и воспользовался). Если так уж прям нравится, то предлагаю пойти дальше. Вот эти ваши таблицы функций ... ничего не напоминают? = Дело в том, что таблица функций есть всегда. Ею является образ exe. То есть моя идея состоит в следующем. В начале времён серверу передаётся просто копия экзешника (или библиотеки), который работает на клиенте. Далее, когда понадобится десериализация, предлагается класть в пакет его размер, а за ним - декорированное имя функции, которая "сертифицирована" проводить десериализацию этого пакета :

Код

    *(unsigned int*)stream = size;
    memcpy_s(stream + SIZE_LENGTH, LP_DESERIALIZATION_PROC_LENGTH,
        deserializeMangledName, LP_DESERIALIZATION_PROC_LENGTH);


Сервер получил этот stream, считал размер пакета и имя функции. Имея последнее, сервер лезет в эталонную таблицу и загружает оттуда точку входа функции-десериализатора :

Код

    // Extract a deserialization function pointer from the stream.
    HMODULE hModule = LoadLibrary(L"Classes.dll");
    if (!hModule) return -1;
    LPDESERIALIZE lpDeserialize = (LPDESERIALIZE)GetProcAddress(hModule,
        stream + SIZE_LENGTH);
    if (!lpDeserialize) return -1;
    LPVOID a = lpDeserialize(stream);


Готово. Копия объекта загружена в LPVOID a. 

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

Архив с полным решением присоединён.

Присоединённый файл ( Кол-во скачиваний: 7 )
Присоединённый файл  Koder.rar 43,99 Kb


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
Lazin
Дата 19.2.2008, 14:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(tol05 @  19.2.2008,  12:17 Найти цитируемый пост)
Из статической ф-ции производного класса нельзя вызвать статическую ф-цию базового класса

это на каком языке? на плюсах можно, если позволяет видимость...


Цитата(marcusmae @  19.2.2008,  13:16 Найти цитируемый пост)
Далее, когда понадобится десериализация, предлагается класть в пакет его размер, а за ним - декорированное имя функции, которая "сертифицирована" проводить десериализацию этого пакета

а если завтра тебе понадобится добавить десяток новых классов, как быть?
PM MAIL Skype GTalk   Вверх
marcusmae
Дата 19.2.2008, 14:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 5
Всего: 39



Цитата(Lazin @  19.2.2008,  14:44 Найти цитируемый пост)
а если завтра тебе понадобится добавить десяток новых классов, как быть?


ну, понадобится иметь для них десяток функций сериализации - по своей собственной для каждого класса. Ну и декорированные имена через dumpbin посмотреть и забить в константы. Что-то мне подсказывает, что если всё аккуратно сделать, то можно обойтись без имён - одними указателями. По идее, если dll, то у неё фиксированная виртуальная адресация, и адрес функции у клиента и сервера должен быть одинаковый.

Цитата(Lazin @  19.2.2008,  14:44 Найти цитируемый пост)
это на каком языке? на плюсах можно, если позволяет видимость...

Можно-можно. Просто, для статических функций само понятие наследования отсутствует. Но их всегда можно вызвать явно.

А вот
Цитата(tol05 @  19.2.2008,  12:17 Найти цитируемый пост)
как же тогда инициализировать закрытые члены базового класса?

- хороший довод. По-моему, никак.


Это сообщение отредактировал(а) marcusmae - 19.2.2008, 14:55


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
tol05
Дата 19.2.2008, 15:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 1
Всего: 170



Цитата(marcusmae @  19.2.2008,  13:49 Найти цитируемый пост)
Можно-можно. Просто, для статических функций само понятие наследования отсутствует. Но их всегда можно вызвать явно.

Это называется "нельзя"  smile  smile 

Какое же это наследование, если нужно this в параметры передать??? Я так могу любую ф-цию вызвать и передать указатель на мой класс. Так что, эти классы предками/потомками станут? Я имел в виду использование Base... когда и базовый, и производный класс оперируют с одним и тем же указателем на объект.

Цитата(marcusmae @  19.2.2008,  13:49 Найти цитируемый пост)
хороший довод

мда, по-моему тоже...  smile 

ну да ладно... этот пост можно считать оффтопом.  smile 



--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
georain
Дата 20.2.2008, 01:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 193
Регистрация: 28.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: нет



xvr
Цитата(xvr @  19.2.2008,  08:00 Найти цитируемый пост)
Чем тебя мое решение не устроило (на 2й странице 3е сверху)?

Потому что решение более сложное, а строка
Код

#define CREATE_FABRIC(Type) static Fabric<Type> instance_of_class_fabric_for_##Type;

обязывающая для каждого класса писать
Код

CREATE_FABRIC(ClassName)

остаётся, в чём выгода?


tol05
Цитата(tol05 @  19.2.2008,  12:17 Найти цитируемый пост)
по поводу статических ф-ций - это ИМХО плохо. Какое преимущество их использования? Из статической ф-ции производного класса нельзя вызвать статическую ф-цию базового класса, как же тогда инициализировать закрытые члены базового класса? В производном классе к ним доступа нет, а в потоке данные о них есть smile Передавать указатель на текущий объект производного класса в метод его же базового класса? ... Извините ...

потому что
Цитата(georain @  19.2.2008,  01:42 Найти цитируемый пост)
внутри static create ,будет вызываться функция - член десериализатор с "каскадной" функциональностью либо поток будет передаваться конструктору

а сама функция create ни как в наследовании не участвует, нам от неё только адрес нужен, и чтоб в классе была, чтобы всегда знать где такую функцию искать (по моему логично функцию создающую конкретный класс держать поближе к самому классу).


marcusmae
Цитата(marcusmae @  19.2.2008,  13:16 Найти цитируемый пост)

Я тут ночью думал-думал и вот что надумал.

развеселил, хохот в час ночи. Возможно это даже будет работать, но мне кажется это не очень кроссплатформенно, этож на win-lin-mac-bsd-и.т.д. должно работать, а разный порядок байтов на разных машинах, сомнительное предложение, но прикольно!  smile 
PM MAIL   Вверх
xvr
Дата 20.2.2008, 08:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(georain @ 20.2.2008,  01:38)
xvr
Цитата(xvr @  19.2.2008,  08:00 Найти цитируемый пост)
Чем тебя мое решение не устроило (на 2й странице 3е сверху)?

Потому что решение более сложное, а строка
Код

#define CREATE_FABRIC(Type) static Fabric<Type> instance_of_class_fabric_for_##Type;

обязывающая для каждого класса писать
Код

CREATE_FABRIC(ClassName)

остаётся, в чём выгода?

В том, что:
1) Не надо добавлять никаких enum'ов, ID и пр.
2) Количество типов классов может быть любым (не ограничено размером числа, задающего тип)
3) Полная проверка на этапе сериализации, что CREATE_FABRIC не забыли указать (увы, может не сработать при раздельных sender'е и reviever'е)
4) Не нужен никакой switch и никакая другая централизованная обработка - потенциальное место где можно забыть что-то добавить.
5) CREATE_FABRIC - это ЕДИНСТВЕННОЕ что добавляется при сериализации нового класса

П1-4 следствия П5.

PM MAIL   Вверх
Страницы: (4) Все 1 2 [3] 4 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1130 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.