使用基类的通用方法指针来调用派生类的方法 [英] Using a generic method pointer of a base class to call methods of derived classes

查看:133
本文介绍了使用基类的通用方法指针来调用派生类的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建一个事件处理系统,其中对象可以订阅其他对象广播的事件,并在广播该事件时调用方法。我试图实现这个单例类的 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆