1

According to Wikipedia, Multiple Dispatch is when

... a function or method can be dynamically dispatched based on the run time (dynamic) type of more than one of its arguments.

However, in C++ I can override a function in the derived class:

#include <iostream>

using namespace std;

class Base
{
public:
    virtual void method(int a) { cout << a; }
    virtual void method(int a, int b) { cout << a + b; }
};

class Derived: public Base
{
    void method(int a) { cout << a * 10 << endl; }
    void method(int a, int b) { cout << (a + b) * 10 <<endl; }
};

int main()
{
    Base* derived = new Derived;
    derived->method(1);
    derived->method(1, 2);
    return 0;
}

Here the method is being bound at runtime (because I am using virtual) and the particular method is selected based on the input parameters - how is this any different from the Wikipedia description of multiple dispatch?

Secondary question: What is the advantage (if any) to languages which support multiple dispatch if this combination of polymorphism and method overloading exists in C++?

Mike Vella
  • 10,187
  • 14
  • 59
  • 86
  • 1
    here your dispatch on `this` argument only. `foo(derived, derived)` would require multiple dispatch. The generic example is `isCollide(object1, object2)` which depend of both object1 and object2 type. – Jarod42 Feb 05 '14 at 15:18

4 Answers4

4

It's being bound at run time according to just one argument, the object it's called on. Virtual functions provide single dispatch according to the (dynamic) type of the object they're called on.

The choice of overload based on the number and (static) type of the other arguments is made at compile time.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
4

No. A candidate is selected statically by the compiler based on the static types of the receiver and the arguments. Then, at runtime, only the dynamic type of the receiver is used to bind the invocation to the most specific overriding method. The dynamic types of the arguments play no role in the dynamic binding phase.

In your particular case this means that for the call derived->method(1);, the compiler looks at the static types of the receiver (Base) and of the actual arguments (int). It then searches, among all methods of Base (inherited or declared in Base) for the one that matches best; this is Base::method(int). At runtime, the runtime system looks at the dynamic type of the receiver (Derived) for the most specific method that overrides Base::method(int), which is Derived::method(int), and calls that method with the given actual argument (1).

Likewise for the second call.

Kristian Duske
  • 1,769
  • 9
  • 14
  • So what is the advantage (if any) to languages which support multiple dispatch if this combination of polymorphism and method overloading exists? – Mike Vella Feb 05 '14 at 15:40
  • Let class B extend class A. Let A have a method doIt(A* a) and B have a method doIt(B* b). Now let A* ab = new B() and then do ab->doIt(ab);. In a language with dynamic multiple dispatch, this will call B::doIt, and in a language with static multiple dispatch, i.e. overloading, this will call A::doIt because the dynamic type of the actual argument is not considered in the latter, but not in the former case. – Kristian Duske Feb 05 '14 at 17:18
1

It's not multiple dispatch because the runtime selection is only being done based on one parameter: the type of the object "derived". The function overload resolution is handled at compile time.

Nathan Monteleone
  • 5,430
  • 29
  • 43
1
virtual void Base::method(int a);

can be seen as

/*virtual*/ void method(Base&, int a);

So, in your case, you have

derived->method(1); will dispatch between:

/*virtual*/ void method(Base&, int a);
/*virtual*/ void method(Derived&, int a);

And derived->method(1, 2); will dispatch between:

/*virtual*/ void method(Base&, int a, int b);
/*virtual*/ void method(Derived&, int a, int b);

And in both case, there is only dispatched according to one argument.

With

void method2(Base&, Base&);
void method2(Derived&, Base&);
void method2(Base&, Derived&);
void method2(Derived&, Derived&);

If you wanted that (with Base* derived = new Derived) method2(*derived, *derived); calls void method2(Derived&, Derived&); then it requires multiple dispatch.
(Currently, it calls void method2(Base&, Base&);).

Jarod42
  • 203,559
  • 14
  • 181
  • 302