我正在尝试创建一个事件处理系统,其中对象可以订阅由其他对象广播的事件,并在广播该事件时调用方法。我正在尝试使用名为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);
到目前为止一切顺利!我的单元测试现在运行得很好。
答案 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 */
}