Question

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++?

Was it helpful?

Solution

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.

OTHER TIPS

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.

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.

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&);).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top