Действительно ли возможно сериализировать и десериализовать класс в C++?

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

Например, ниже - класс ученика, который будет использовать его в нашем коде.

public class Student {

    private int id;

    public int getId() {
        return this.id;
    }

    public setId(int newId) {
        this.id = newId;
    }
}

Приведенный ниже код дает вам исключение с нулевым указателем.

public class School {

    Student obj_Student;

    public School() {
        try {
            obj_Student.getId();
        }
        catch(Exception e) {
            System.out.println("Null Pointer ");
        }
    }
}

Поскольку вы используете Obj_Student, но вы забыли инициализировать его, как в правильном коде, показанном ниже:

public class School {

    Student obj_Student;

    public School() {
        try {
            obj_Student = new Student();
            obj_Student.setId(12);
            obj_Student.getId();
        }
        catch(Exception e) {
            System.out.println("Null Pointer ");
        }
    }
}
131
задан 9 revs, 6 users 36% 10 January 2013 в 05:04
поделиться

5 ответов

Boost::serialization библиотека обрабатывает это скорее изящно. Я использовал его в нескольких проектах. Существует пример программы, показывая, как использовать его, здесь .

единственный собственный способ сделать это состоит в том, чтобы использовать потоки. Это по существу весь Boost::serialization, библиотека делает, она расширяет потоковый метод путем установки платформы, чтобы записать объекты в подобный тексту формат и считать их из того же формата.

Для встроенных типов или Ваших собственных типов с operator<< и operator>> правильно определенный, это довольно просто; см. C++ FAQ для получения дополнительной информации.

92
ответ дан 24 November 2019 в 00:17
поделиться

Повышение является хорошим предложением. Но если Вы хотели бы к самокрутке, это не настолько твердо.

В основном Вам просто нужен способ создать график объектов и затем произвести их к некоторому формату структурированного хранилища (JSON, XML, YAML, безотносительно). Создание графика так же просто как использование отмечающего рекурсивного достойного объектного алгоритма и затем вывод всех отмеченных объектов.

я написал статью, описывающую элементарное (но все еще мощный) система сериализации. Можно найти это интересным: Используя SQLite как Дисковый Формат файла, Часть 2 .

16
ответ дан 24 November 2019 в 00:17
поделиться

Насколько "встроенные" библиотеки идут, << и >> были зарезервированы специально для сериализации.

необходимо переопределить << для вывода объекта к некоторому контексту сериализации (обычно iostream) и >> для чтения данных назад из того контекста. Каждый объект ответственен за вывод его агрегированных дочерних объектов.

Этот метод хорошо работает, пока Ваш граф объектов не содержит циклов.

, Если это делает, затем необходимо будет пользоваться библиотекой для контакта с теми циклами.

13
ответ дан 24 November 2019 в 00:17
поделиться

Я рекомендую буферы протокола Google . У меня был шанс к тест-драйву библиотека по новому проекту, и это удивительно просто в использовании. Библиотека в большой степени оптимизирована для производительности.

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

13
ответ дан 24 November 2019 в 00:17
поделиться

Я использую следующий шаблон для реализации сериализации:

template <class T, class Mode = void> struct Serializer
{
    template <class OutputCharIterator>
    static void serializeImpl(const T &object, OutputCharIterator &&it)
    {
        object.template serializeThis<Mode>(it);
    }

    template <class InputCharIterator>
    static T deserializeImpl(InputCharIterator &&it, InputCharIterator &&end)
    {
        return T::template deserializeFrom<Mode>(it, end);
    }
};

template <class Mode = void, class T, class OutputCharIterator>
void serialize(const T &object, OutputCharIterator &&it)
{
    Serializer<T, Mode>::serializeImpl(object, it);
}

template <class T, class Mode = void, class InputCharIterator>
T deserialize(InputCharIterator &&it, InputCharIterator &&end)
{
    return Serializer<T, Mode>::deserializeImpl(it, end);
}

template <class Mode = void, class T, class InputCharIterator>
void deserialize(T &result, InputCharIterator &&it, InputCharIterator &&end)
{
    result = Serializer<T, Mode>::deserializeImpl(it, end);
}

Здесь T тип, который Вы хотите сериализировать Mode, фиктивный тип для дифференциации между различными видами сериализации, например, то же целое число может быть сериализировано как прямой порядок байтов, обратный порядок байтов, varint, и т.д.

По умолчанию Serializer делегаты задача к сериализируемому объекту. Для созданного в типах необходимо сделать шаблонную специализацию Serializer.

шаблоны функций Удобства также предоставлены.

, Например, сериализация с прямым порядком байтов целых чисел без знака:

struct LittleEndianMode
{
};

template <class T>
struct Serializer<
    T, std::enable_if_t<std::is_unsigned<T>::value, LittleEndianMode>>
{
    template <class InputCharIterator>
    static T deserializeImpl(InputCharIterator &&it, InputCharIterator &&end)
    {
        T res = 0;

        for (size_t i = 0; i < sizeof(T); i++)
        {
            if (it == end) break;
            res |= static_cast<T>(*it) << (CHAR_BIT * i);
            it++;
        }

        return res;
    }

    template <class OutputCharIterator>
    static void serializeImpl(T number, OutputCharIterator &&it)
    {
        for (size_t i = 0; i < sizeof(T); i++)
        {
            *it = (number >> (CHAR_BIT * i)) & 0xFF;
            it++;
        }
    }
};

Затем для сериализации:

std::vector<char> serialized;
uint32_t val = 42;
serialize<LittleEndianMode>(val, std::back_inserter(serialized));

Для десериализации:

uint32_t val;
deserialize(val, serialized.begin(), serialized.end());

из-за абстрактной логики итератора, это должно работать с любым итератором (например, потоковыми итераторами), указатель, и т.д.

0
ответ дан 24 November 2019 в 00:17
поделиться
Другие вопросы по тегам:

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