我正在设计一个必须本质上支持操作历史记录(撤消/重做)和序列化的系统。它包含各种实体,许多实体以图的形式链接。
我想通过让操作了解对象的创建、销毁和链接来自动化大部分历史记录工作。我面临的问题如下:
假设我创建对象A,然后创建对象B,然后链接A和B。这是三个动作。现在撤消所有操作,操作将移至“重做”列表。现在,重新做一遍。这意味着创建了一个新 的 A对象,创建了一个新的 B对象。为了重做链接操作,我需要知道作用于旧 A和B对象的“链接”动作现在将应用于新 的 A和B对象。
一个简单的重定位表就可以解决问题;创建新对象时,只需将旧地址映射到新地址,并使用它来解释历史日志中的任何链接关系。问题是,如果涉及多重继承会发生什么?也就是说,链接可能引用指向 A 基址的指针,而不是A本身,因此地址可能与重定位表中的地址不同。
系统必须处理数百 GB 的内存,因此出于性能原因,我宁愿不要只是在内部丢弃所有指针并切换到全局唯一 ID 并一直执行表查找。为所有内容都添加一个虚拟基类也是不可取的,因为其中一些类型非常轻量级。
问题是,除了我提到的两个替代方案之外,是否可以通过指向(可能多个)基类之一的指针来唯一标识对象?我是否应该放弃自动化并为所涉及的每种类型编写专门的代码?
编辑:
也许我对冗长的解释不够清楚。这是一个展示问题的简单示例:
#include <iostream>
using namespace std;
struct A { int x; };
struct B { int y; };
struct AB : A, B { int z; };
int main()
{
AB ab;
AB* pab = &ab;
A* pa = &ab;
B* pb = &ab;
cout << "pab: " << pab << endl;
cout << "pa: " << pa << endl;
cout << "pb: " << pb << endl;
}
一种可能的输出是:
pab: 0x7fff30b6a400
pa: 0x7fff30b6a400
pb: 0x7fff30b6a404
如您所见,尽管它们来自同一个对象,但它们pb
的值与 不同。pab
我需要一种方法来知道它们都标识同一个对象,原因如上所述(执行/撤消操作可能会在新位置重新创建对象,因此必须更新所有指向它的指针。)