既存のライブラリに新しい機能を追加しようとしています。ルート クラスがアクセサを持つように、クラス階層に新しいデータを追加する必要があります。誰でもこのデータを取得できるのは、サブクラスのみが設定できるようにする必要があります (つまり、public getter と protected setter)。
下位互換性を維持するために、次のことを行ってはならないことはわかっています (リストには、問題に関連するアクションのみが含まれています)。
- 仮想機能の追加または削除
- メンバー変数の追加または削除
- 既存のメンバー変数の型を変更する
- 既存の関数のシグネチャを変更
このデータを階層に追加するには 2 つの方法が考えられます。新しいメンバー変数をルート クラスに追加する方法と、純粋な仮想アクセサー関数を追加する方法 (データをサブクラスに格納できるようにする方法) です。ただし、下位互換性を維持するために、これらのいずれも実行できません。
ライブラリは広範囲にpimplイディオムを使用していますが、残念ながら、私が修正しなければならないルート クラスはこのイディオムを使用していません。ただし、サブクラスはこのイディオムを使用します。
私が考えることができる唯一の解決策は、静的ハッシュマップでメンバー変数をシミュレートすることです。したがって、静的ハッシュ マップを作成し、この新しいメンバーをそこに格納して、静的アクセサーを実装することができます。このようなもの(疑似C ++で):
class NewData {...};
class BaseClass
{
protected:
static setNewData(BaseClass* instance, NewData* data)
{
m_mapNewData[instance] = data;
}
static NewData* getNewData(BaseClass* instance)
{
return m_mapNewData[instance];
}
private:
static HashMap<BaseClass*, NewData*> m_mapNewData;
};
class DerivedClass : public BaseClass
{
void doSomething()
{
BaseClass::setNewData(this, new NewData());
}
};
class Outside
{
void doActions(BaseClass* action)
{
NewData* data = BaseClass::getNewData(action);
...
}
};
さて、この解決策は機能するかもしれませんが、非常に醜いと思います (もちろん、非静的アクセサー関数を追加することもできますが、これでは醜さが取り除かれません)。
他の解決策はありますか?
ありがとうございました。