2017-10-25 9 views
2

私はC++を使ってゲームコードを書いています。私はChildのメンバー関数をデリゲートにバインドしたいと思います。継承クラスのメンバーファンク터を渡す

私はこの単純化されたコードのようinit_and_bind機能を使用したい:私はWidgetクラスでinit_and_bindを実装したいので、私はコード以下のように実装

class Parent { 
protected: 
    Widget* widget; 
}; 

class Child : public Parent { 
public: 
    void foo() { 
     widget->init_and_bind(this, &Child::bar); 
    } 

    void bar() { /* do something */ } 
}; 

// pre-defined in engine 
void Delegate::bind(Parent* object, void(Parent::* function)()); 

void Widget::init_and_bind(Parent* object, void(Parent::* function)()) { 
    init(); 
    delegate->bind(object, function); 
} 

しかし、それはありません作業。 init_and_bindの2番目のパラメータはParentのメンバファンクタ型のみを受け入れるためです。だから私は子供のメンバーのファンクタを渡すことはできません。だから私はテンプレートとreinterpret_castを使用しようとしました:

しかし、それも動作しません。 ChildのファンクタをParentのファンクタにキャストできないためです。

したがって、init_and_bindの第2引数はどのようなタイプですか?

+2

'static_cast'ではなく、' reinterpret_cast'です。 – StoryTeller

+0

@StoryTellerああ、それは動作します、ありがとう!しかし、なぜ 'reiniterpret_cast'がコンパイルされていないのか分かりません。 –

+1

異なるジョブの異なるキャスト。コンパイラはあなたが正しいことを使っていることをチェックします。キャストする必要がある場合は、常にデフォルトで 'static_cast'で開始してください。 – StoryTeller

答えて

2

即時解決はstatic_castになりますが、init_and_bindをテンプレートにしないでください。生成されたコードは常に同じになります。唯一の違いは、実際のキャストの実行方法にある可能性があります。

非常に小さな違いのため、かなりのコードが膨らんできます。私は代わりにその違いをカプセル化することをお勧めします。そのためWidgetにヘルパータイプを追加します。

class Widget { 
    struct MemFunc { 
    void(Parent::* function)(); 
    template<class T> 
    MemFunc(void(T::* func)()) : 
     function(static_cast<void(Parent::*)()>(func)) 
    {} 
    }; 

    void init_and_bind(Parent* object, MemFunc mf) { 
    init(); 
    delegate->bind(object, mf.function); 
    } 
}; 

その方法は、テンプレートを必要とするコードのごく小さな部分は実際にはテンプレート化されています。最高のものは、発信側で透過的に起こっています。そして、おそらく肥大化を引き起こすことさえないでしょう。とにかく元のテンプレート以外のバージョンでは、発信者をstatic_castにする必要があったためです。