4

私はこのようなインターフェースを持っています(実際のライブラリコードではこれよりもはるかに長いものを除いて)

struct IFoo
{
    virtual void onA(A& a) = 0;
    virtual void onB(A& a) = 0;
    virtual void onC(A& a) = 0;
};

のさまざまなリスナーを実装するのが一般的ですIFoo。このため、私は次のようなヘルパークラスを設計しました。

template <class T>
struct IFooHelper {
    virtual void onA(A& a) { static_cast<T*>(this)->onGeneric(a); }
    virtual void onB(B& b) { static_cast<T*>(this)->onGeneric(b); }
    virtual void onC(C& c) { static_cast<T*>(this)->onGeneric(c); }
};

そのため、リスナーで多くの一般的な動作を行う場合、すべての関数の仮想オーバーライドを提供する必要はなく、IFoo次のようなことができます。

struct Fox : public IFooHelper<Fox>
{
    template <class T> void onGeneric(T& t) { //do something general }
    void onD(D& d) { //special behavior only for a type D }
};

これは素晴らしくうまく機能しましたが、今はいくつかの一般的な動作が必要なリスナーを実装してから、たとえば、どのタイプの呼び出しであったかなどのカウンターを更新しています。言い換えると、A,B,C上記のタイプしかない場合、リスナーは次のようになります。

struct Ugly : public IFooHelper<Ugly>
{
    void onA(A& a) { //8 lines of common code; //update some counter for type A objs; }
    void onB(B& b) { //8 lines of common code; //update some counter for type B objs; }
    void onC(C& c) { //8 lines of common code; //update some counter for type C objs; }
};

ここでは、呼び出しは非常に高速である必要があり(ルックアップがないため)、理想的には、を利用しIFooHelperて一般的な動作をテンプレートメソッドに引き上げ、それでもどういうわけかタイプを区別できるようになります。静的なconschar*配列へのオフセットを持つ、またはそれに応じてchar *である値自体を持つテンプレート専用構造体のようなものを考えていましTた。より良い方法はありますか?

4

1 に答える 1

1

あなたが探しているものを完全に理解しているかどうかはわかりませんが、試してみます。最初のステップとして、これを考慮してください。

struct NotSoUgly : public IFooHelper<NotSoUgly>
{
    void updateCounter(A& a) { //update some counter for type A objs; }
    void updateCounter(B& b) { //update some counter for type B objs; }
    void updateCounter(C& c) { //update some counter for type C objs; }

    template <class T> void onGeneric(T& t) {
        //8 lines of common code;
        updateCounter(t);
    }
};

メソッドの内容を見せていただければ、さらに改善することができます。updateCounter()そのための単一のジェネリック実装も考え出すことができますが、コードを見ないと推測するのは困難です。

于 2013-02-17T11:05:46.860 に答える