使用基类的泛型方法指针来调用派生类的方法

时间:2012-07-14 21:00:17

标签: c++

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

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

PDObjectEventHandler将处理的所有对象的基类。 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_PDObjectPDObject的派生类,只需在调用wasPoked时翻转test_poke位。

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

我正在尝试做甚么可能吗?我可以使用此泛型方法指针类型来引用派生类的方法吗?或者我的方法是完全有缺陷的?

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

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

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

1 个答案:

答案 0 :(得分:1)

static_cast 确实只需要将类型Child::*指针指向成员转换为Base::*类型,但请请记住,如果您偶然在Base的实例(而不是相关的Child)上使用指向成员指针,这可能会非常危险。


在下面的示例中,我们使用与前面描述的完全相同的方法,尽管在Child::func类型的对象上调用Base会导致 undefined-behavior ,因为我们正在访问函数内部的不存在的成员。

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 */
}