At
this point you may have a question: “If this technique is so important,
and if it makes the ‘right’ function call all the time, why is it
an option? Why do I even need to know about it?”
This
is a good question, and the answer is part of the fundamental philosophy of
C++: “Because it’s not quite as efficient.”
You can see from the previous assembly-language output that instead of one
simple CALL to an absolute address, there are two more sophisticated assembly
instructions required to set up the virtual function call. This requires both
code space and execution time.
Some
object-oriented languages have taken the approach that late binding is so
intrinsic to object-oriented programming that it should always take place, that
it should not be an option, and the user shouldn’t have to know about it.
This is a design decision when creating a language, and that particular path is
appropriate for many languages.
[34]
However, C++ comes from the C heritage, where efficiency is critical. After
all, C was created to replace assembly language for the implementation of an
operating system (thereby rendering that operating system – Unix –
far more portable than its predecessors). One of the main reasons for the
invention of C++ was to make C programmers more efficient.
[35]
And the first question asked when C programmers encounter C++ is “What
kind of size and speed impact will I get?” If the answer were,
“Everything’s great except for function calls when you’ll
always have a little extra overhead,” many people would stick with C
rather than make the change to C++. In addition, inline functions would
not be possible, because virtual functions must have an address to put into the
VTABLE. So the virtual function is an option,
and
the language defaults to nonvirtual, which is the fastest configuration.
Stroustrup stated that his guideline was “If you don’t use it, you
don’t pay for it.”
Thus
the
virtual
keyword
is provided for efficiency tuning. When designing your classes, however, you
shouldn’t be worrying about efficiency tuning. If you’re going to
use polymorphism, use virtual functions everywhere. You only need to look for
functions to make non-virtual when looking for ways to speed up your code (and
there are usually much bigger gains to be had in other areas).
Anecdotal
evidence suggests that the size and speed impacts of going to C++ are within
10% of the size and speed of C, and often much closer to the same. The reason
you might get better size and speed efficiency is because you may design a C++
program in a smaller, faster way than you would using C.
[34]Smalltalk,
for instance, uses this approach with great success.
[35]At
Bell labs, where C++ was invented, there are a
lot
of C programmers. Making them all more efficient, even just a bit, saves the
company many millions.