virtual functions & constructors
When an object containing virtual
functions is created, its VPTR must be initialized to
point to the proper VTABLE. This must be done before
there’s any possibility of calling a virtual function. As you might guess,
because the constructor has the job of bringing an object into existence, it is
also the constructor’s job to set up the VPTR. The compiler secretly
inserts code into the beginning of the constructor that initializes the VPTR.
And as described in Chapter 14, if you don’t explicitly create a
constructor for a class, the compiler will synthesize one for you. If the class
has virtual functions, the synthesized constructor will include the proper VPTR
initialization code. This has several implications.
The first concerns efficiency. The reason
for inline functions is
to reduce the calling overhead for small functions. If C++ didn’t provide
inline functions, the preprocessor might be used to create these
“macros.” However, the preprocessor has no concept of access or
classes, and therefore couldn’t be used to create member function macros.
In addition, with constructors that must have hidden code inserted by the
compiler, a preprocessor macro wouldn’t work at all.
You must be aware when hunting for
efficiency
holes that the compiler is inserting hidden code into your constructor function.
Not only must it initialize the VPTR, it must also check the value of
this (in case the operator new returns zero) and call
base-class constructors. Taken together, this code can impact what you thought
was a tiny inline function call. In particular, the size of the constructor may
overwhelm the savings you get from reduced function-call overhead. If you make a
lot of inline constructor calls, your code size can grow without any benefits in
speed.
Of course, you probably won’t make
all tiny constructors non-inline right away, because they’re much easier
to write as inlines. But when you’re tuning your code, remember to
consider removing the inline
constructors.