4

我正在为 C++ 中的对象图实现“克隆”功能,部分问题是确保如果有两个指向同一个对象的指针,它不会被克隆两次。我通过保留 amap<void*, void*>来做到这一点,它将原始对象作为键,将克隆版本作为值。克隆对象时,我使用模板函数检查对象是否在地图中 - 如果是,我将其返回为static_cast<T*>,否则,我克隆它并将原始和克隆存储在地图中,并隐式转换为void*.

这种方案的问题在于,如果一个对象在两个地方被不同的类型(例如,通过接口与具体类型)引用,则强制转换void*可能不会产生相同的值。这意味着该对象被克隆了两次。

我在网上寻找现有的解决方案,并意识到 Boost.Serialization 必须处理同样的问题。但是在浏览了它的源代码之后,我找不到实际跟踪对象指针的部分。

任何人都可以通过建议可行的设计或指出 Boost 代码中执行此操作的部分来提供帮助吗?

4

2 回答 2

4

在存储之前,将指针转换为dynamic_cast<void*>- 这将为您提供指向最派生对象的 void 指针;对于相同的对象,此 void 指针将存储相同的地址。

另请参阅此问题

于 2012-01-23T09:24:25.433 回答
1

我不相信 boost 序列化以某种超级聪明的方式处理这个问题。看看这个base_object函数——看来你必须手动说出基类是什么。从这里很明显如何获得相同的指针。另请注意,对于序列化派生类,只有虚拟类才能正确保存,非虚拟类,如标准布局类型,您必须序列化派生类。我不知道他们在这种情况下是否处理共享指针。

所以基本的想法是,如果你有一个虚拟类,那么基础必须有一个“串行”功能。如果你转换到这个基数,你就有一个公共指针,仍然可以调用虚拟串行函数。

您最好只创建一个全局identify<T>模板并将其专门用于所有需要它的类型。可能容易出错,但提升方法也绝不会避免错误。

我在 boost 序列化方面做了很多工作,但避免了指针逻辑——它真的很混乱,所以我基本上只是不做那种级别的序列化(我的序列化数据中没有指针)。

于 2012-01-23T08:50:14.207 回答