Multiple Dispatch

今天在看文章的时候遇到了multiple dispatch这个术语。看看了wiki,写得云里雾里。最后搜了搜资料,基本上搞清楚了。

multiple dispatch的混淆之处在于其和object system结合在一起。当然wiki上写得很清楚:“a function or method can be dynamically dispatched based on the run time (dynamic) type of more than one of its arguments.”。这摆明了就是和object system紧耦合在了一起。更准确地来讲multiple dispath其实就是专门针对OO中的消息通信的一个概念。与之相关的概念还有single dispatch和dynamic dispatch。

如 果不考虑object system,我觉得function overloading也可以算是一种multiple dispatch。function overloading需要根据参数的类型以及个数来决议调用函数,过程上来讲和multiple dispatch的定义很像,都是通过参数类型来决定调用函数。但是有一个很重要的不同点:multiple dispatch是runtime行为,而function overloading是编译器在compile-time时就决议好了。

要彻底理解multiple dispatch还要从OO的定义说起:OO其实就是对象以及对象间的通信。C++对于对象间的通信采用了函数调用的方式,这与objective-c有点区别。C++的通信方式可以简单地以object.method()的方式呈现。method其实就是信息,object.method()的意思就是method这个信息被派发给了object。这就是所谓有single dispatch,因为信息只能被派发给一个对象。

先举一个简单的例子。有一个状态机S会接受N种不同的trigger,每个trigger要触发当前状态下的一个动作。

class AbstractTrigger;
class AbstractState
{
public:
    virtual void AcceptTrigger( AbstractTrigger* _trigger ) = 0;
};

class AbstractTrigger
{
    /*....*/
};
class State1 : public AbstractState
{
public:
  void AcceptTrigger( AbstractTrigger* _trigger )
  {
    /*....*/
  }
};
class Trigger1 : public AbstractTrigger 
{
  
/*....*/
};

目前的难点在于如何根据trigger的类型来选择合适的动作。一种可行的方法是在State1::AcceptTrigger中判断_trigger的实际类型,然后再根据类型去执行相应的动作。这种作法属于过街老鼠式的做法,code review八成是过不去的。另外一种做法是采用visitor pattern的做法,代码如下:

class AbstractTrigger;
class Trigger1;
class AbstractState
{
public:
    virtual void AcceptTrigger( AbstractTrigger* _trigger ) = 0;
    virtual void Action1( void ) = 0;
};

class AbstractTrigger
{
public:
    virtual void Action( AbstractState* _state ) = 0;
};

class State1 : public AbstractState
{
    void AcceptTrigger( AbstractTrigger* _trigger )
    {
        _trigger->Action 
    }

    void Action1( void )
    {
        /*....*/
    }
};

class Trigger1 : public AbstractTrigger
{
public:
    void Action( AbstractState* _state )
    {
        _state->Action1();
    }
};

我们在AbstractState中声明了纯虚函数Action1,子类实现它以完成Trigger1时的动作。当然也可以加入Action2, Action3 ... ActionN,分别对应Trigger2, Trigger3 ... TriggerN。在State1::AcceptTrigger中将_trigger派发给了Trigger1,再由Trigger1去调用State1::Action1。之所以整个调用过程做得如此复杂,原因在于State1知道怎么做,但是不知道做哪些;而Trigger1知道做哪些,却不知道怎么做。简言之,在运行时要做哪个动作是由State1和Trigger1两个对象同时决定的,缺一不可。而在C++中一个消息只能同时发给一个对象,在程序需要发消息给多个对象的时候,只能一个一个地去遍历。Lisp有可以把一个消息同时发给多个对象的能力,这种能力就叫做multiple dispatch。

上面的示例代码也可以叫做double dispatch,在wiki上有详细的解释。

参考资料:

转载于:https://www.cnblogs.com/hughlo/archive/2013/05/28/3100830.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值