使用基类的通用方法指针来调用派生类的方法 [英] Using a generic method pointer of a base class to call methods of derived classes
问题描述
我试图创建一个事件处理系统,其中对象可以订阅其他对象广播的事件,并在广播该事件时调用方法。我试图实现这个单例类的 EventHandler
。对象调用 EventHandler
上的一个公共方法来订阅他们对某个对象广播的事件:
I'm trying to create an event handling system where objects can subscribe to events broadcasted by other objects and call a method when that event is broadcast. I'm trying to implement this with a singleton class called EventHandler
. Objects call a public method on EventHandler
that subscribes them to events broadcast by a certain object:
void startWatchingObjectEvent(PDObject * object, PDEvent event, PDObject* listener, PDReceiver receiver);
PDObject
将由 EventHandler
处理的对象。 PDEvent
只是一个标识事件的唯一字符串。
PDObject
is a base class for all the objects that will be handled by the EventHandler
. PDEvent
is simply a unique string that identifies the Event.
PDReceiver
是我碰到问题的地方。我有它typedef到 PDObject
类的方法指针:
PDReceiver
is where I'm running into issues. I have it typedef'd to a method pointer on the PDObject
class:
typedef void (PDObject::*PDReceiver)(PDObject*, PDEvent);
现在 PDObject
真的有任何方法, EventHandler
将要调用,但派生类 PDObject
将会,我想创建一个通用类型 EventHandler
可以存储将应用于 PDObject
的任何派生类。我以这种方式实现了 EventHandler
,并尝试编写一个单元测试,以确保它工作正常:
Now the PDObject
class itself doesn't really have any methods that EventHandler
is going to call, but derived classes of PDObject
will, and I wanted to create a generic type that EventHandler
could store that would apply to any derived classes of PDObject
. I implemented EventHandler
this way and tried writing a unit test to make sure it's working okay:
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
test_poke
时转换 wasPoked
位的 >
Test_PDObject
is a derived class of PDObject
that just flips a wasPoked
bit when test_poke
is called.
问题是,编译器不喜欢我尝试分配 Test_PDObject
到 PDReceiver
的方法,因为 PDReceiver
被定义为 PDObject
。
The issue is that the compiler doesn't like me trying to assign a method of Test_PDObject
to the type PDReceiver
since PDReceiver
is defined as a method of PDObject
.
我想要做的事情是否可能?我可以使用这个通用方法指针类型来引用派生类的方法吗?或者是我的方法完全有缺陷?
Is what I'm trying to do even possible? Can I use this generic method pointer type to refer to methods of derived classes? Or is my approach just entirely flawed?
编辑:我想出了我可以使用 static_cast
如下:
I figured out I can use static_cast
to cast the method pointer of the derived class to a method pointer of the base class like so:
PDReceiver receiver = static_cast<PDReceiver>(&Test_PDObject::test_poke);
到目前为止这么好!我的单元测试现在运行正常。
And so far so good! My unit tests are working perfectly now.
推荐答案
一个 static_cast 类型 Child :: *
的指针到成员键入 Base :: *
,但请记住,如果您在 Base
的实例上意外使用指针到成员相关 Child
)。
A static_cast is indeed all that is required to cast a pointer-to-member of type Child::*
to type Base::*
, but please remember that this might be quite dangerous if you by accident use the pointer-to-member on an instance of Base
(and not the related Child
).
尽管在类型 Base
的对象上调用 Child :: func
会导致 undefined-behavior ,因为我们正在访问函数内部Base的一个不存在的成员。
In the example below we use the same exact approach as described earlier, though calling Child::func
on a object of type Base
is causing undefined-behavior since we are accessing a non-existent member of Base inside the function.
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 */
}
这篇关于使用基类的通用方法指针来调用派生类的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!