Double Dispatch

Recently I was visiting one company and got C++ interview question: What is double dispatch. I studied C++ quite long time ago and that question confused me.
Single Dispatch is calling virtual method based on V-Table (run-time) but double dispatch?
After interview I always review subjects which made me hard time. Thats only reason for going to interview – refresh memory of forgotten things and learn something new.

Single Dispatch

Single dispatch is calling of virtual method – its basics of polymorphism in C++.

// By Boris Ivanov (C) 2016.
#include <iostream>
#include <string>
using namespace std;

class A{
public:
    virtual void work() = 0;
};

class A1: public A{
    virtual void work (){
        cout << "A1 do work" << "\n"; 
    } 
}; 

int main( ) { 
    A* a = new A1(); 
    a->work(); 
}

Result :
A1 do work

Double dispatch

Double dispatch is the ability of selecting dynamically a method not only according to the run-time type of the receiver (single dispatch), but also to the run-time type of the argument.

This mechanism demonstrate power of dynamic binding in object-oriented languages, so enhancing re-usability and separation of responsibilities. However, many mainstream languages, such as C++. C# and Java, do not provide it, resorting to only single dispatch. Lets see how to implement it.

 Imagine we have 2 types of objects and want to simulate their interaction. Assume we have Sphere like objects and Surfaces. Make the pure Abstract. Derive from them Ball, Baloon, Table and Window.

Task is to implement their interaction through up-casted pointers;

// By Boris Ivanov (C) 2016.
class Surface;
class Table;
class Window;

class Ball;
class Baloon;


class Sphere{
public:
    virtual void hit (Surface& a) = 0;
    virtual void RealTimeHit (Table& a) = 0;
    virtual void RealTimeHit (Window& a) = 0;
};

class Surface {
public:
    virtual void hit (Sphere& b) = 0;
    virtual void RealTimeHit (Ball& b) = 0;
    virtual void RealTimeHit (Baloon& b) = 0;

};

class Ball : public Sphere
{
     void hit (Surface& s)
    {
        s.RealTimeHit(*this);
    }

     void RealTimeHit (Table& a){
        cout << "Ball hit Table and bounced" << "\n";
    }

     void RealTimeHit (Window& a){
        cout << "Ball hit Window and broken it!" << "\n";
    }
};

class Baloon : public Sphere
{
     void hit (Surface& s)
    {
        s.RealTimeHit(*this);
    }

     void RealTimeHit (Table& a){
        cout << "Baloon hit Table and bounced" << "\n";
    }

     void RealTimeHit (Window& a){
        cout << "Baloon hit Window and bounced it!" << "\n";
    }
};

class Table : public Surface
{
     void hit (Sphere& s)
    {
        s.RealTimeHit(*this);
    }

     void RealTimeHit (Ball& a){
        cout << "Table hit by Ball but survived" << "\n";
    }

     void RealTimeHit (Baloon& a){
        cout << "Table hit by Baloon and baloon stuck in Jam!" << "\n";
    }
};

class Window : public Surface
{
     void hit (Sphere& s)
    {
        s.RealTimeHit(*this);
    }

     void RealTimeHit (Ball& a){
        cout << "Window hit by Ball. Oops!" << "\n";
    }

     void RealTimeHit (Baloon& a){
        cout << "Window hit by baloon! Nothing serious!" << "\n"; 
     } 
   }; 

 int main( ) 
 {  
    Sphere * a1 = new Ball(); 
    Sphere * a2 = new Baloon(); 
    Surface * b1 = new Table(); 
    Surface * b2 = new Window(); 

    a1->hit(*b1); // Ball > Table
    a2->hit(*b2); // Baloon > Window
    a1->hit(*b2); // Ball > Window
    a2->hit(*b1); // Baloon > Table

    return 0;
}

Result:

Table hit by Ball but survived
Window hit by baloon! Nothing serious!
Window hit by Ball. Oops!
Table hit by Baloon and baloon stuck in Jam!

Leave a Reply

Your email address will not be published. Required fields are marked *