The
problem with
Wind2.cpp
can be seen by running the program. The output is
Instrument::play.
This is clearly not the desired output, because you happen to know that the
object is actually a
Wind
and not just an
Instrument.
The call should resolve to
Wind::play.
For that matter, any object of a class derived from
Instrument
should have its version of
play
used, regardless of the situation.
However,
the behavior of
Wind2.cpp
is not surprising, given C’s approach to functions. To understand the
issues, you need to be aware of the concept of
binding.
Function
call binding
Connecting
a function call to a function body is called
binding.
When binding is performed before the program is run (by the compiler and
linker), it’s called
early
binding.
You may not have heard the term before because it’s never been an option
with procedural languages: C compilers have only one kind of function call, and
that’s early binding.
The
problem in the above program is caused by early binding because the compiler
cannot know the correct function to call when it has only an
Instrument
address.
The
solution is called
late
binding,
which means the binding occurs at run-time, based on the type of the object.
Late binding is also called
dynamic
binding
or
run-time
binding.
When a language implements late binding, there must be some mechanism to
determine the type of the object at run-time and call the appropriate member
function. That is, the compiler still doesn’t know the actual object
type, but it inserts code that finds out and calls the correct function body.
The late-binding mechanism varies from language to language, but you can
imagine that some sort of type information must be installed in the objects
themselves. You’ll see how this works later.