2

我正在尝试创建一个事件处理系统,其中对象可以订阅其他对象广播的事件并在该事件被广播时调用方法。我正在尝试使用一个名为EventHandler. 对象调用一个公共方法,该方法EventHandler将它们订阅到某个对象广播的事件:

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

PDObject是所有将由EventHandler. PDEvent只是一个标识事件的唯一字符串。

PDReceiver是我遇到问题的地方。我将它类型定义为PDObject类上的方法指针:

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

现在PDObject该类本身实际上并没有任何要调用的方法,EventHandler而是将要调用的派生类PDObject,我想创建一个EventHandler可以存储的泛型类型,该类型将适用于PDObject. 我EventHandler以这种方式实现并尝试编写单元测试以确保它正常工作:

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翻转wasPoked一点。test_poke

问题是编译器不喜欢我尝试将方法分配给Test_PDObject类型PDReceiver,因为PDReceiver它被定义为PDObject.

我想要做的甚至可能吗?我可以使用这个泛型方法指针类型来引用派生类的方法吗?还是我的方法完全有缺陷?

编辑:我发现我可以使用static_cast将派生类的方法指针转换为基类的方法指针,如下所示:

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

到目前为止一切顺利!我的单元测试现在运行良好。

4

1 回答 1

1

static_cast确实是将type 的指向成员的指针Child::*强制转换为type所需的全部内容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 回答