Как Вы 'десериализовываете' производный класс от сериализированных данных?

Как Вы 'десериализовываете' производный класс от сериализированных данных? Или возможно я должен сказать, там лучший способ 'десериализовать' данные в производные классы?

Например, предположите, что у Вас был чистый виртуальный базовый класс (B), который наследован тремя другими классами, X, Y и Z. Кроме того, мы имеем метод, сериализируем (), который переведет X:B, Y:B и Z:B в сериализированные данные.

Таким образом, это может быть убито через сокет, именованный канал, и т.д. к удаленному процессу.

Проблема, которую я имею, как мы создаем соответствующий объект из сериализированных данных?

Единственное решение, которое я могу предложить, включает идентификатор в сериализированные данные, которые указывают на заключительный тип производного объекта. Где получатель, первые синтаксические анализы поле производного типа от сериализированных данных, и затем использует оператор переключения (или своего рода логика как этот) для вызова соответствующего конструктора.

Например:

B deserialize( serial_data )
{
    parse the derived type from the serial_data

    switch (derived type)
        case X
            return X(serial_data)
        case Y
            return Y(serial_data)
        case Z
            return Z(serial_data)
}

Таким образом, после изучения производного объекта вводят, мы вызываем соответствующего конструктора производного типа.

Однако это чувствует себя неловким и громоздким. Я надеюсь, что существует более красноречивый способ сделать это. Есть ли?

9
задан John Rocha 16 July 2010 в 20:57
поделиться

2 ответа

Фактически, это более общая проблема, чем сериализация, называемая виртуальным конструктором .

Традиционный подход - это Factory , которая на основе идентификатора возвращает правильный производный тип. Есть два решения:

  • метод switch , как вы заметили, хотя вам нужно разместить в куче
  • метод прототипа

Метод прототипа выглядит следующим образом :

// Cloneability
class Base
{
public:
  virtual Base* clone() const = 0;
};

class Derived: public Base
{
public:
  virtual Derived* clone() const { return new Derived(*this); }
};

// Factory
class Factory
{
public:
  Base* get(std::string const& id) const;
  void set(std::string const& id, Base* exemplar);

private:
  typedef std::map < std::string, Base* > exemplars_type;
  exemplars_type mExemplars;
};

Сделать Factory синглтоном довольно традиционно, но это совсем другое дело.

Для собственно десериализации будет проще, если у вас есть виртуальный метод deserialize для вызова объекта.

РЕДАКТИРОВАТЬ: Как работает Factory?

В C ++ вы не можете создать тип, о котором вы не знаете. Идея выше заключается в том, что задача создания производного объекта передается классу Derived посредством метода clone .

Далее идет Завод . Мы собираемся использовать карту , которая будет связывать «тег» (например, «Derived» ) с экземпляром объекта (скажем, Derived здесь) .

Factory factory;
Derived derived;
factory.set("Derived", &derived);

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

std::unique_ptr<Base> base = factory.get("Derived");

Под крышкой Factory найдет Base * , связанный с тегом "Derived" , и вызовет метод clone объекта. Это фактически (здесь) создаст объект типа среды выполнения Derived .

Мы можем проверить это с помощью оператора typeid :

assert( typeid(base) == typeid(Derived) );
2
ответ дан 5 December 2019 в 02:07
поделиться
inmemory:
--------
type1 {
  chartype a;
  inttype b;
};
serialize(new type1());

serialized(ignore { and ,):
---------------------------
type1id,len{chartypeid,adata,inttypeid,bdata}

Я полагаю, что в идеальном протоколе сериализации каждый непримитивный тип должен иметь префикс typeid, len. Даже если вы сериализуете один тип, который не является производным от чего-либо, вы должны добавить идентификатор типа, потому что другой конец должен знать, какой тип он получает (независимо от структуры наследования). Таким образом, вы должны упомянуть идентификаторы производных классов в сериализации, потому что логически это разные типы. Поправьте меня, если я ошибаюсь.

0
ответ дан 5 December 2019 в 02:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: