Реализация отслеживания объектов, как в Boost :: Serialization - PullRequest
4 голосов
/ 23 января 2012

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

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

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

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

Ответы [ 2 ]

4 голосов
/ 23 января 2012

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

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

1 голос
/ 23 января 2012

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

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

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

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

...