Реализация отслеживания объектов, как в Boost::Serialization

Я реализую функцию "клонирования" для графа объектов в C++, и часть проблемы состоит в том, чтобы гарантировать, что, если есть два указателя на один и тот же объект, он не будет клонирован дважды. Я сделал это, сохранив map<void*, void*> это сохраняет исходный объект в качестве ключа и клонированную версию в качестве значения. При клонировании объекта я использую функцию шаблона, чтобы проверить, есть ли объект на карте - если да, я возвращаю его с static_cast<T*>иначе я клонирую его и сохраняю оригинал и клон на карте с неявным преобразованием в void*,

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

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

Может кто-нибудь помочь, предложив дизайн, который работает, или указав часть кода Boost, который делает это?

2 ответа

Решение

Перед сохранением наведите указатель с dynamic_cast<void*> - это даст вам пустой указатель на самый производный объект; этот указатель void для тех же объектов будет иметь один и тот же сохраненный адрес.

Смотрите также этот вопрос.

Я не верю, что сериализация Boost делает это очень умным способом. Посмотрите на base_object функция - кажется, вы должны вручную сказать, что такое базовый класс. Отсюда очевидно, как получить тот же указатель. Также обратите внимание, что для сериализации производных классов правильно будут сохранены только виртуальные классы, таким образом, не виртуальные, как стандартные типы макетов, вы должны сериализовать производный класс. Я понятия не имею, обрабатывают ли они общий указатель в этом случае.

Поэтому основная идея заключается в том, что если у вас есть виртуальный класс, база должна иметь своего рода "последовательную" функцию. Если вы приведете к этой базе, у вас будет общий указатель, и вы все равно сможете вызвать виртуальную последовательную функцию.

Вам может быть лучше просто создать глобальный identify<T> шаблон и специализировать его для всех типов, которые нуждаются в этом. Может быть подвержен ошибкам, но ни в коем случае не делает буст-подход без ошибок.

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

Другие вопросы по тегам