2

アクションの履歴(元に戻る/やり直し)とシリアル化を本質的にサポートする必要があるシステムを設計しています。さまざまなエンティティが含まれており、その多くはグラフとしてリンクされています。

オブジェクトの作成、破棄、リンクについてアクションに通知することで、ほとんどの履歴ログ作業を自動化したいと思っています。私が直面している問題は次のとおりです。

オブジェクトAを作成し、次にオブジェクトBを作成し、次にABをリンクするとします。これらは3つのアクションです。すべてを元に戻すと、アクションは「やり直し」リストに移動します。ここで、すべてをやり直します。これは、新しい Aオブジェクトが作成され、新しい Bオブジェクトが作成されることを意味します。また、リンク操作をやり直すには、古い AオブジェクトとBオブジェクトに作用した「リンク」アクションが新しい AオブジェクトとBオブジェクトに適用されることを知る必要があります。

単純な再配置テーブルでうまくいきます。新しいオブジェクトを作成するときは、古いアドレスを新しいアドレスにマップし、それを使用して履歴ログからのリンク関係を解釈します。問題は、多重継承が関係している場合はどうなるかということです。つまり、リンクはA自体ではなく、Aのベースへのポインタを参照している可能性があるため、アドレスは再配置テーブルのアドレスとは異なる可能性があります。

システムは数百GBのメモリを処理する必要があるため、パフォーマンス上の理由から、すべてのポインタを内部で破棄してグローバルな一意のIDに切り替え、常にテーブルルックアップを実行するのではなく、一部のタイプは非常に軽量であるため、すべての仮想基本クラスをスローすることも望ましくありません。

問題は、私が言及した2つの選択肢以外に、(おそらく複数の)基本クラスの1つへのポインターを介してオブジェクトを一意に識別することは可能ですか?これを自動化し、関係するタイプごとに専用のコードを書くことをあきらめる必要がありますか?

編集:

たぶん私は長い説明で十分に明確ではありませんでした。問題を示す簡単な例を次に示します。

#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;
}

考えられる出力の1つは次のとおりです。

pab: 0x7fff30b6a400
pa: 0x7fff30b6a400
pb: 0x7fff30b6a404

ご覧のとおり、同じオブジェクトからのものであっても、とpbは異なる値を持っています。pab両方が同じオブジェクトを識別することを知る方法が必要です。理由は上記で説明しました(do / undo操作はオブジェクトを新しい場所に再作成する可能性があるため、オブジェクトへのすべてのポインターを更新する必要があります)。

4

0 に答える 0