I l@ve RuBoard Previous Section Next Section

11.1 What Are Multimethods?

In C++, polymorphism essentially means that a given function call can be bound to different implementations, depending on compile-time or runtime contextual issues.

Two types of polymorphism are implemented in C++:

  • Compile-time polymorphism, supported by overloading and template functions[2]

    [2] A more generous view of polymorphism would qualify automatic conversions as the crudest form of polymorphism. They allow, for example, std::sin to be called with an int although it was written for a double. This polymorphism through coercion is only apparent, because the same function call will be issued for both types.

  • Runtime polymorphism, implemented with virtual functions

Overloading is a simple form of polymorphism that allows multiple functions with the same name to coexist in a scope. If the functions have different parameter lists, the compiler can differentiate among them at compile time. Overloading is simple syntactic sugar, a convenient syntactic abbreviation.

Template functions are a static dispatch mechanism. They offer more sophisticated compile-time polymorphism.

Virtual member function calls allow the C++ runtime support, instead of the compiler, to decide which actual function implementation to call. Virtual functions bind a name to a function implementation at runtime. The function called depends on the dynamic type of the object for which you make the virtual call.

Let's now see how these three mechanisms for polymorphism scale to multiple objects. Overloading and template functions scale to multiple objects naturally. Both features allow multiple parameters, and intricate compile-time rules govern function selection.

Unfortunately, virtual functions—the only mechanism that implements runtime polymorphism in C++—are tailored for one object only. Even the call syntax—obj.Fun (arguments)—gives obj a privileged role over arguments. (In fact, you can think of obj as nothing more than one of Fun's arguments, accessible inside Fun as *this. The Dylan language, for example, accepts the dot call syntax only as a particular expression of a general function-call mechanism.)

We define multimethods or multiple dispatch as the mechanism that dispatches a function call to different concrete functions depending on the dynamic types of multiple objects involved in the call. Because we can take compile-time multiobject polymorphism for granted, we need only implement runtime multiobject polymorphism. Don't be worried; there's a lot left to talk about.

    I l@ve RuBoard Previous Section Next Section