4

C ++でオブジェクトのグラフに「クローン」関数を実装していますが、問題の一部は、同じオブジェクトへのポインターが2つある場合に、それが2回クローンされないようにすることです。これmap<void*, void*>は、元のオブジェクトをキーとして保持し、複製されたバージョンを値として保持することによって行いました。オブジェクトのクローンを作成するときは、テンプレート関数を使用して、オブジェクトがマップにあるかどうかを確認します。ある場合は、で返しますstatic_cast<T*>。そうでない場合は、クローンを作成して元のオブジェクトを保存し、暗黙的にマップに変換してクローンを作成しvoid*ます。

このスキームの問題は、オブジェクトが2つの場所で異なるタイプ(たとえば、インターフェイスと具象タイプ)によって参照されている場合、キャスト先void*が同じ値にならない可能性があることです。これは、オブジェクトが2回複製されることを意味します。

私はこれに対する既存の解​​決策をウェブで調べ、Boost.Serializationが同じ問題に対処しなければならないことに気づきました。しかし、そのソースを調べた後、オブジェクトへのポインターを実際に追跡する部分を見つけることができませんでした。

誰かがうまくいくデザインを提案することによって、またはこれを行うBoostコードの部分を指摘することによって助けることができますか?

4

2 に答える 2

4

保存する前に、ポインターをキャストします- これにより、最も派生したオブジェクトdynamic_cast<void*>への無効ポインターが得られます。この void ポインターは、同じオブジェクトに対して同じアドレスを格納します。

この質問も参照してください。

于 2012-01-23T09:24:25.433 に答える
1

ブーストシリアライゼーションがこれを非常に巧妙な方法で処理するとは思いません。関数を見てくださいbase_object。基本クラスが何であるかを手動で指定する必要があるようです。ここから、同じポインタを取得する方法は明らかです。また、派生クラスをシリアル化する場合、仮想クラスのみがそのように正しく保存されることに注意してください。非仮想クラスは、標準のレイアウト タイプのように、派生クラスをシリアル化する必要があります。その場合、共有ポインターを処理するかどうかはわかりません。

したがって、基本的な考え方は、仮想クラスがある場合、ベースにはある種の「シリアル」機能が必要であるということです。このベースにキャストすると、共通のポインターがあり、仮想シリアル関数を呼び出すことができます。

グローバルidentify<T>テンプレートを作成し、それを必要とするすべてのタイプに特化した方がよい場合があります。エラーが発生しやすい可能性がありますが、ブースト アプローチでもエラーが回避されるわけではありません。

私はブーストシリアライゼーションで多くの作業を行いましたが、ポインターロジックを避けました.それは本当に混乱したので、基本的にそのレベルのシリアライゼーションを行いません.

于 2012-01-23T08:50:14.207 に答える