2

オブジェクトが他のオブジェクトによってブロードキャストされたイベントをサブスクライブし、そのイベントがブロードキャストされたときにメソッドを呼び出すことができるイベント処理システムを作成しようとしています。と呼ばれるシングルトンクラスでこれを実装しようとしていEventHandlerます。EventHandlerオブジェクトは、特定のオブジェクトによってブロードキャストされるイベントにサブスクライブするパブリックメソッドを呼び出します。

void startWatchingObjectEvent(PDObject * object, PDEvent event, PDObject* listener, PDReceiver receiver);

PDObjectは、によって処理されるすべてのオブジェクトの基本クラスですEventHandlerPDEventイベントを識別する単純な一意の文字列です。

PDReceiver私が問題に直面しているところです。PDObjectクラスのメソッドポインタにtypedefしました:

typedef void (PDObject::*PDReceiver)(PDObject*, PDEvent);

これで、クラス自体には実際に呼び出すPDObjectメソッドはありませんが、willの派生クラスがあり、の派生クラスに適用できる格納可能なジェネリック型を作成したいと思いました。私はこの方法を実装し、単体テストを作成して、正常に機能していることを確認しました。EventHandlerPDObjectEventHandlerPDObjectEventHandler

const PDEvent Test_PokeEvent = "Test_PokeEvent";

void Test_EventHandler_sendObjectMessage()
{
    EventHandler& eventh = EventHandler::instance();
    Test_PDObject caster;
    Test_PDObject listener;
    PDReceiver receiver = &Test_PDObject::test_poke;
    eventh.startWatchingObjectEvent(&caster, Test_PokeEvent, &listener, (listener.*receiver)(&caster, Test_PokeEvent));
    eventh.sendObjectEvent(&caster, Test_PokeEvent);
    assert(listener.test_wasPoked());
}

Test_PDObjectは、が呼び出されたときに少しPDObject反転する派生クラスです。wasPokedtest_poke

問題は、がのメソッドとして定義されているため、コンパイラがのメソッドをTest_PDObjectタイプに割り当てようとすることを好まないことです。PDReceiverPDReceiverPDObject

私がやろうとしていることは可能ですか?このジェネリックメソッドポインタ型を使用して、派生クラスのメソッドを参照できますか?それとも私のアプローチは完全に欠陥がありますか?

編集:次static_castのように、派生クラスのメソッドポインターを基本クラスのメソッドポインターにキャストするために使用できることがわかりました。

PDReceiver receiver = static_cast<PDReceiver>(&Test_PDObject::test_poke);

そしてこれまでのところとても良いです!私の単体テストは現在完全に機能しています。

4

1 に答える 1

1

type のポインタへのメンバを typeにキャストするために必要なのはstatic_castだけですが、関連するインスタンスではなく (のインスタンスで誤ってポインタへのメンバを使用すると、非常に危険になる可能性があることに注意してください。)。Child::*Base::*BaseChild


以下の例では、前述とまったく同じアプローチを使用してChild::funcいますが、型のオブジェクトを呼び出すと、関数内の Baseの存在しないメンバーにアクセスしているため、未定義の動作Baseが発生します。

struct Base {
  /* ... */
};

struct Child : Base {

  void func () {
    this->x = 123;
  }

  int x;
};

int
main (int argc, char *argv[])
{
  typedef void (Base::*BaseFuncPtr) (); 

  BaseFuncPtr ptr_to_child_func = static_cast<BaseFuncPtr> (&Child::func);

  Base b;

  (b.*ptr_to_child_func) (); /* undefined-behavior */
}
于 2012-07-16T05:57:38.753 に答える