2010-11-26 11 views
1

im newty.deのLars HaendelのFunctor tutorialに続いてコールバックシステムを設定します。私はちょっと混乱しています。私は誰かが私を助けることを望んでいます。ここでC++ Functorコールバックの設定

は私のFunctorテンプレートは、私がやりたいことは基本的に他の.dllが私HookGameEvent()関数を使用すると、ゲームイベントが呼び出されたとき、私はベクトルを介して実行することができます許可され

#include <igameevents.h> 

// Abstract Base Class (Functor) 
class TBaseCallback 
{ 
public: 

    // two possible functions to call member function. virtual cause derived 
    // classes will use a pointer to an object and a pointer to a member function 
    // to make the function call 
    virtual void operator()(IGameEvent *pEvent){}; // call using operator 
    virtual void Call(IGameEvent *pEvent) {};  // call using function 
}; 


// Derived Template Class 
template <class TClass> class TEventCallback : public TBaseCallback 
{ 
private: 

    void (TClass::*funcPtr)(IGameEvent*);  // pointer to member function 
    TClass* thisPtr;       // pointer to object 

public: 

    // constructor - takes pointer to an object and pointer to a member and stores them in two private variables 
    TEventCallback(TClass* _thisPtr, void(TClass::*_funcPtr)(const char*)) 
    { thisPtr = _thisPtr; funcPtr=_funcPtr; }; 

    // override operator "()" 
    virtual void operator()(IGameEvent *pEvent) 
    { (*thisPtr.*funcPtr)(pEvent); };   // execute member function 

    // override function "Call" 
    virtual void Call(IGameEvent *pEvent) 
    { (*thisPtr.*funcPtr)(pEvent); };   // execute member function 
}; 

あり| |私のフックのリスト、イベント名が一致するかどうかを確認し、必要に応じてコールバックを実行します。私が混乱しているのは、このようなHookEvent構造体にコールバックを格納する方法です。

std::vector<EventHook*> m_EventHooks; 

struct EventHook 
{ 
    char *name; 
    EventHookMode mode; 
    //TEventCallback<IGameEvent*> pEventCallback; 
}; 

私は今はコメントアウトしていますが、私は混乱しているものと混乱しているものを明確にしています。誰でも助けてもらえれば大いに感謝します。

+0

TEventCallbackクラスの関数ポインタが(const char *)パラメータで定義されていますが、コード内で(IGameEvent *)を使用して呼び出すことに気づかずにいました。 – Daemin

+0

typedefing関数型の値を指摘します。 @ブレット:もしあなたがエラーメッセージを扱っているなら、それをあなたの質問に含めれば、私たちにとって非常に役に立ちます。コードがあなたが他の理由で望むものを達成することに失敗している場合は、それらのことを教えてもらえます。あなたが何を起こそうとしているのか、実際に何が起こっているのかを教えてください。そうでなければ、ただ推測しています。 – outis

+0

私が持っていた問題は、それを構造体に入れる方法でした。(const char *)は、そのチュートリアルを使用していたときから残されていました。 –

答えて

3

ほとんどの人は継承を理解していません。一般に、派生クラスは実装の詳細です。名前を発する唯一の時間は、それらを構築することです。さらに、基底の仮想関数はプライベートで純粋でなければならず、派生クラスでは完全にアクセスできない必要があります。これはC++の設計上のバグです。これは強制されません。

 
struct TBaseCallback 
    void operator()(IGameEvent *pEvent) { _Call(pEvent); }; 
    void Exec(IGameEvent *pEvent) { _Call(PEvent); } 
private: 
    virtual void _Call(IGameEvent *pEvent)=0; 
}; 

struct EventHook 
{ 
    char *name; 
    EventHookMode mode; 
    TBaseCallback *p; 
    void dispatch(char *msg; IGameEvent *e) const { 
     if(strcmp(msg,name)==0) p->Exec(e); 
    } 
}; 

このデザインでは、TBaseCallbackから派生したクラスには何も変わりません。抽象だけが公に見えるはずです。通常のコードではこれを強制するのは難しいです..DLLを使用して派生クラスを取得するときは、派生クラスのセットがオープン/任意/無限/不確定(選択を取る)であるため、絶対的に必須です。

ところで、これをより複雑な抽象化にプッシュすると、オブジェクトオリエンテーションが壊れた概念である理由が間もなくわかります。 DLLがロードされた派生クラスでは、は(それらがクローズ/特定/有限/確定的であるため)dynamic_castスイッチでチートできません。

0

コールバックを行うクラスは、呼び出すFunctorオブジェクトのリストを保持する必要があります。そして、通知取得に興味を持っている誰もがフックの彼の独自の実装を作成します

struct EventHook 
{ 
    ... 
    virtual void notifyMe(); 
} 

:これらは今EventHookは、仮想関数を持つべきであるあなたの

std::vector<EventHook*> m_EventHooks; 

だろう

struct MyEventHook : public EventHook 
{ 
    virtual void notifyMe() { ... whatever I want to do in that case ... } 
} 

ポリモーフィズムの不思議を通し、m_EventHooksコンテナのすべての要素を繰り返し処理し、それらのオブジェクトをnotifyMe()と呼ぶと、正しいクラスのバージョンはcal LED。

0

pEventCallbackの型では、テンプレートパラメータはクラス型でなければなりませんが、実際にはポインタ型です。 (どのような種類のコールバックラップを限定するものではないが)一つの修正は基本型を使用することです:

struct EventHook 
{ 
    char *name; 
    EventHookMode mode; 
    TBaseCallback* pCallback; 
}; 

TEventCallbackのAPIへのより多くのだし、それはEventHookを通じてアクセスできるようにする必要がある場合は、内のコードを移動する必要がありますTEventCallbackは、オブジェクトとそのメソッドを別のサブクラスに処理します。オフトピック

// Example EventCallback that takes other args 
class EventCallback : public TBaseCallback { 
public: 
    EventCallback(); 
    EventCallback(const EventArgs& evtArgs); 
    // EventCallback specific methods ... 
    virtual EventArgs& args(); 
    virtual const EventArgs& args() const; 
} 

/* TReturn allows for calling methods with a non-void return. Return value is ignored. 
*/ 
template <class TClass, typename TReturn = void> 
class TMethodCallback : public EventCallback 
{ 
private: 
    typedef TReturn (TClass::*TMeth)(IGameEvent*); 
    TMeth funcPtr;  // pointer to member function 
    TClass* thisPtr;       // pointer to object 

public: 

    // constructor - takes pointer to an object and pointer to a member and stores them in two private variables 
    TMethodCallback(TClass* _thisPtr, TMeth _funcPtr) 
    { thisPtr = _thisPtr; funcPtr=_funcPtr; }; 

    // override operator "()" 
    virtual void operator()(IGameEvent *pEvent) 
    { (*thisPtr.*funcPtr)(pEvent); };   // execute member function 

    // override function "Call" 
    virtual void Call(IGameEvent *pEvent) 
    { (*thisPtr.*funcPtr)(pEvent); };   // execute member function 
}; 

あなたにもTBaseCallback::CallコールTBaseCallback::operator()のデフォルトの実装を行うことがあります。

void TBaseCallback::Call(IGameEvent *pEvent) { this->operator()(pEvent); }; 

+0

ありがとう、これは私が持っていたすべての問題をカバーするようです。 1つの質問は、基本的に、別のプラグインがフックを作成するために私のものを使用するときです。ここで、どうやって見えるのですか?EventHookError HookEvent(const char * name、void * thisptr、void * callback、EventHookMode mode = EventHookMode_Post);構造体のコールバックがTBaseCallbackの場合、クラス/ funcPtrにはなりませんので、実際にコールバックを格納することはできません。 –

+0

APIクライアントがコールバックオブジェクトの作成を担当します。 'HookEvent'のプロトタイプは' EventHookError HookEvent(const char * name、TBaseCallback * pCallback、EventHookMode mode = EventHookMode_Post) 'です。 – outis

0

テンプレートのインスタンス化でTの代わりにT *を使用しているため、複雑なコンパイルエラーが発生すると思います。

はこれを試してみてください:それはあなたが何をしたい場合は

struct EventHook 
{ 
    char *name; 
    EventHookMode mode; 
    TEventCallback<IGameEvent> pEventCallback; 
}; 

は、コンパイルする必要があります。

関連する問題