Double Dispatch - Double Dispatch Is More Than Function Overloading

Double Dispatch Is More Than Function Overloading

At first glance, double dispatch appears to be a natural result of function overloading. Function overloading allows the function called to depend on the type of the argument. Function overloading however is done at compile time using "name mangling" where the internal name of the function has the argument's type encoded in it. So for example a function foo(int) would internally be called __foo_i and function foo(double) would be called __foo_d. So there is no runtime overhead because there is no name collision and calling an overloaded function goes through at most one virtual table just like any other function. Dynamic dispatch is only based on the type of the calling object. Consider the following example, written in C++, of collisions in a game:

class SpaceShip {}; class ApolloSpacecraft : public SpaceShip {}; class Asteroid { public: virtual void CollideWith(SpaceShip&) { cout << "Asteroid hit a SpaceShip" << endl; } virtual void CollideWith(ApolloSpacecraft&) { cout << "Asteroid hit an ApolloSpacecraft" << endl; } }; class ExplodingAsteroid : public Asteroid { public: virtual void CollideWith(SpaceShip&) { cout << "ExplodingAsteroid hit a SpaceShip" << endl; } virtual void CollideWith(ApolloSpacecraft&) { cout << "ExplodingAsteroid hit an ApolloSpacecraft" << endl; } };

If you have

Asteroid theAsteroid; SpaceShip theSpaceShip; ApolloSpacecraft theApolloSpacecraft;

then, because of function overloading,

theAsteroid.CollideWith(theSpaceShip); theAsteroid.CollideWith(theApolloSpacecraft);

will print Asteroid hit a SpaceShip and Asteroid hit an ApolloSpacecraft respectively, without using any dynamic dispatch. Furthermore

ExplodingAsteroid theExplodingAsteroid; theExplodingAsteroid.CollideWith(theSpaceShip); theExplodingAsteroid.CollideWith(theApolloSpacecraft);

will print ExplodingAsteroid hit a SpaceShip and ExplodingAsteroid hit an ApolloSpacecraft respectively, again without dynamic dispatch.

With a reference to an Asteroid, dynamic dispatch is used and

Asteroid& theAsteroidReference = theExplodingAsteroid; theAsteroidReference.CollideWith(theSpaceShip); theAsteroidReference.CollideWith(theApolloSpacecraft);

prints ExplodingAsteroid hit a SpaceShip and ExplodingAsteroid hit an ApolloSpacecraft, again as expected. However,

SpaceShip& theSpaceShipReference = theApolloSpacecraft; //note the type of the pointer and the type of the object. theAsteroid.CollideWith(theSpaceShipReference); theAsteroidReference.CollideWith(theSpaceShipReference);

The desired behaviour is to bind these calls to the function that takes theApolloSpacecraft as its argument, as that is the instantiated type of the variable, meaning the expected output would be Asteroid hit an ApolloSpacecraft and ExplodingAsteroid hit an ApolloSpacecraft, but the output is actually Asteroid hit a SpaceShip and ExplodingAsteroid hit a SpaceShip. The problem is that, while virtual functions are dispatched dynamically in C++, function overloading is done statically.

Read more about this topic:  Double Dispatch

Famous quotes containing the words double and/or function:

    I know [my label], in any case: a double face, a charming Janus, and underneath, the house motto: “Be wary”. On my business cards: “Jean-Baptiste Clamence, actor”.
    Albert Camus (1913–1960)

    As a medium of exchange,... worrying regulates intimacy, and it is often an appropriate response to ordinary demands that begin to feel excessive. But from a modernized Freudian view, worrying—as a reflex response to demand—never puts the self or the objects of its interest into question, and that is precisely its function in psychic life. It domesticates self-doubt.
    Adam Phillips, British child psychoanalyst. “Worrying and Its Discontents,” in On Kissing, Tickling, and Being Bored, p. 58, Harvard University Press (1993)